一:帝国之仓-DAO

1.持久层支持

为什么需要使用Spring对持久层的支持?1):原生操作持久层API方式,麻烦.2):Spring对事务支持非常优秀.传统JDBC:1:代码臃肿,重复2:处理异常3:控制事务Spring JDBC:1:简洁,优雅,简单2:运行异常3:Spring事务管理![Spring为什么对持久层提供技术支持](https://img-blog.csdn.net/20180406231810368?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)![Spring提供的对应模板类](https://img-blog.csdn.net/2018040623194871?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

2.JDBC

需求:使用JDBC完成CRUD操作.依赖jar:mysql-connector-java-5.x.11.jar:MySQL驱动包druid连接池spring-jdbc-版本.RELEASE.jar:支持JDBCspring-tx-版本.RELEASE.jar:支持事务

dao

public interface EmployeeDAO {void save(Employee emp);void update(Employee emp);void delete(Long id);Employee get(Long id);List<Employee> listAll();
}

impl

public class EmployeeDAOImpl implements EmployeeDAO{private JdbcTemplate jdbcTemplate;public void setDataSource(DataSource dataSource){this.jdbcTemplate = new JdbcTemplate(dataSource);}public void save(Employee emp) {jdbcTemplate.update("INSERT INTO employee (name,age) VALUES (?,?)",emp.getName(),emp.getAge());}public void update(Employee emp) {jdbcTemplate.update("UPDATE employee SET name=? ,age=? WHERE id=?",emp.getName(),emp.getAge(),emp.getId());}public void delete(Long id) {jdbcTemplate.update("DELETE FROM employee where id = ?",id);}public Employee get(Long id) {List<Employee> list = jdbcTemplate.query("SELECT id,name,age eage from employee where id = ?",new Object[]{id},(rs,rowNum)->{//lanmda表达式其实就是匿名内部类的缩写,面向行数的编程Employee e = new Employee();e.setId(rs.getLong("id"));e.setName(rs.getString("name"));e.setAge(rs.getInt("eage"));return e;   });return list.size()==1? list.get(0):null;}public List<Employee> listAll() {return jdbcTemplate.query("SELECT id,name,age eage from employee",new Object[]{},new RowMapper<Employee>(){//把每一行结果集映射成一个Employee对象public Employee mapRow(ResultSet rs, int rowNum) throws SQLException {Employee e = new Employee();e.setId(rs.getLong("id"));e.setName(rs.getString("name"));e.setAge(rs.getInt("eage"));return e;}});}
}

App-context.xml

<context:property-placeholder location="classpath:db.properties" system-properties-mode="NEVER"/><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driverClassName}"></property><property name="url" value="${jdbc.url}"></property><property name="username" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property><property name="initialSize" value="${jdbc.initialSize}"></property></bean><!-- 配置DAO --><bean id="employeeDAO" class="cn.wolfcode.dao.imp.EmployeeDAOImpl"><property name="dataSource" ref="dataSource" ></property></bean>
    1:不建议使用QueryForObject因为得到的结果如果没有会报错2:回顾了一下lambda表达式.3:解释了JDBC底层是怎么处理结果集的![解释JDBC底层处理结果集](https://img-blog.csdn.net/20180407004514737?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

Spring JDBC的其他设计

    1:给jdbcTemplate的一个基类(父类)  将需要的类继承与JdbcDaoSupport,但是任然要为其父类注入DataSource属性然后super.getJdbcTemplate().调用的方法![hibernate等其他类的基类图](https://img-blog.csdn.net/20180407012449666?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)2:将参数用NamedParameterJdbcTemplate来设置NamedParameterJdbcTemplate namedParameterJdbcTemplate = null;namedParameterJdbcTemplate.update("INSERT INTO employee (name,age) VALUES (:ename,:eage)",new HashMap(){{this.put("ename",emp.getName());this.put("eage", emp.getAge());}});![具体参数设置细节](https://img-blog.csdn.net/20180407012153524?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

二:帝国之盾-TX

1.引出事务

dao

    ![根据银行转账案例引出事务](https://img-blog.csdn.net/20180407122553180?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)public class AccountDAOImpl implements IAccountDAO{private JdbcTemplate jdbcTemplate;public void setDataSource(DataSource dataSource){this.jdbcTemplate = new JdbcTemplate(dataSource);}public void transOut(Long outId, int money) {jdbcTemplate.update("UPDATE account set balance = balance - ? where id = ?",money,outId);}public void transIn(Long inId, int money) {jdbcTemplate.update("UPDATE account set balance = balance + ? where id = ?",money,inId);}
}

service

public class AccountServiceImpl implements IAccountService{private IAccountDAO dao;public void setDao(IAccountDAO dao) {this.dao = dao;}public void trans(Long outId, Long inId, int money) {dao.transOut(outId, money);int i = 3 / 0;dao.transIn(inId, money);}
}

App

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {@Autowiredprivate IAccountService service;@Testpublic void testTrans() throws Exception {service.trans(10086L,10010L,1000);}
}

2.事务回顾

    ![何为数据库事务](https://img-blog.csdn.net/20180407122703713?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)数据库并发问题:并发问题类型          产生原因和效果第一类丢失更新        两个事务更新相同数据,如果一个事务提交,另一个事务回滚,第一个事务的更新会被回滚脏读                 第二个事务查询到第一个事务未提交的跟新数据,第二个事务根据该数据执行,但第一个事务回滚第二个事务操作脏数据虚读                一个事务查询到另一个事务已经提交的新数据,导致导致多次查询数据不一致不可重复读           一个事务查询到另一个事务已经修改的数据,导致多次查询数据不一致第二类丢失数据        多个事务同时读取相同数据,并完成各自的事务提交,导致最后一个事务提交会覆盖前面所有事务对数据的改变
    ![事务的隔离级别](https://img-blog.csdn.net/20180407141043712?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)默认情况下MySQL不会出现幻读.除非:select * from 表名 lock in share mode;MySQL中锁基于索引机制,也不会出现第一类丢失更新.Oracle支持 READ COMMITED(缺省) 和 SERIALIZABLE.MySQL支持 四种隔离级别, 缺省为REPEATABLE READ.隔离级别如何选用:隔离界别越高,数据库事务并发执行性能越差,能处理的操作越少.因此在实际项目开发中为了考虑并发性能一般使用READ COMMITED.它能避免丢失跟新和脏读尽管不可重复读和幻读不能避免,更多的情况下使用悲观锁或乐观锁来解决.
事务的类型:本地事务:就是普通事务,能保证单台数据库上的操作ACID,被限定在一台数据库上.分布式事务:涉及多个数据库源的事务,即跨越多台同类或异类数据库的事务(由每台数据库的本地事务组成的),分布式事务旨在保证这些本地事务的所有操作ACID,使事务可以跨越多台数据库;JDBC事务和JTA事务:JDBC事务:就是数据库事务类型中的本地事务,通过Conenction对象的控制来管理事务;JTA事务:JTA指(Java Transaction API).是Java EE数据库事务规范,JTA只提供了事务管理接口,由应用程序服务器厂商提供实现,JTA事务比JDBC更强大,支持分布式事务.按是否通过编程实现事务有声明式事务和编程式事务:编程式事务:通过编写代码来管理事务.声明式事务:通过注解或XML配置来管理事务.

3.Spring对事务支持的API

PlatformTransactionManager:根据TransactionDefinition提供的事务属性配置信息,创建事务.平台的事务管理器,是多种事务管理器的基类,覆盖了处理事务的方法.public interface PlatformTransactionManager {//根据事务定义的环境中返回一个已经存在的事务,如果不存在,则新建一个.TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;//提交事务void commit(TransactionStatus status) throws TransactionException;//回滚事务void rollback(TransactionStatus status) throws TransactionException;}TransactionDefinition:封装事务的隔离级别和超时时间,是否为只读事务和传播规则等事务属性.TransactionStatus:封装了事务的具体运行状态,如是否新开启事务,是否已经提交事务,设置当前事务为rollback-only等.它们三者之间有关联的.
    Hibernate  :  HibernateTransactionManagerJDBC/MyBatis: DataSourceTransactionManager![如何正确的使用JDBC/MyBatis等连接池](https://img-blog.csdn.net/20180407145436503?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

4.事务的传播规则

    ![事务的传播行为](https://img-blog.csdn.net/20180407151009598?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)寄生事务并不是所有的事务管理器都支持,比如HibernateTransactionManager默认就不支持,需要手动去开启JDBC和MyBatis的事务管理器:DataSourceTransactionManager:默认就是支持的.

5.事务配置

    ![<tx:method name=""/>里面的属性配置](https://img-blog.csdn.net/20180407160349699?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

通过XML的方式配置事务的属性

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd" ><context:property-placeholder location="classpath:db.properties" system-properties-mode="NEVER"/><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driverClassName}"></property><property name="url" value="${jdbc.url}"></property><property name="username" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property><property name="initialSize" value="${jdbc.initialSize}"></property></bean><!-- 配置DAO --><bean id="accountDAOImpl" class="cn.wolfcode.dao.imp.AccountDAOImpl"><property name="dataSource" ref="dataSource" ></property></bean><!-- 配置Service --><bean id="accountServiceImpl" class="cn.wolfcode.service.impl.AccountServiceImpl"><property name="dao" ref="accountDAOImpl"></property></bean><!-- ============================================================================= --><!-- 1:WHAT:配置JDBC事务管理器 --><!-- 记得拷贝TX事务这个包 --><bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 2:WHEN:配置事务管理器增强 --><tx:advice id="txAdvice" transaction-manager="txManager"><tx:attributes><tx:method name="trans"/></tx:attributes> </tx:advice><!-- 3:WHERE:配置一个切面 --><aop:config><aop:pointcut expression="execution(* cn.wolfcode.service.*Service.*(..))" id="txPointCut"/><aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/></aop:config><!-- ============================================================================= --><!-- 配置一个CRUD的通用事务的配置 --><tx:advice id="crudAdvice" transaction-manager="txManager"><tx:attributes><!-- service中的查询方法 --><tx:method name="get*" read-only="true" propagation="REQUIRED"/><tx:method name="list" read-only="true" propagation="REQUIRED"/><tx:method name="query*" read-only="true" propagation="REQUIRED"/><!-- service中其他方法(非查询) --><tx:method name="*" propagation="REQUIRED"/></tx:attributes></tx:advice></beans>

6.使用注解配置

domain

@Data
public class Account {private Long id;private int balance;
}

dao

public interface IAccountDAO {/*** 从指定账户转出多少钱* @param outId* @param money*/void transOut(Long outId,int money);/*** 从指定账户转入多少钱* @param inId* @param money*/void transIn(Long inId,int money);
}

impl

@Repository
public class AccountDAOImpl implements IAccountDAO{private JdbcTemplate jdbcTemplate;@Autowiredpublic void setDataSource(DataSource dataSource){this.jdbcTemplate = new JdbcTemplate(dataSource);}public void transOut(Long outId, int money) {jdbcTemplate.update("UPDATE account set balance = balance - ? where id = ?",money,outId);}public void transIn(Long inId, int money) {jdbcTemplate.update("UPDATE account set balance = balance + ? where id = ?",money,inId);}
}

service

public interface IAccountService {/*** 从指定账户转出指定金额给另一个账户* @param outId* @param inId* @param money*/void trans(Long outId,Long inId,int money);
}

impl

@Service
@Transactional
public class AccountServiceImpl implements IAccountService{@Autowiredprivate IAccountDAO dao;public void trans(Long outId, Long inId, int money) {dao.transOut(outId, money);int i = 3 / 0;dao.transIn(inId, money);}@Transactional(readOnly=true)public void list(){}
}

App

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {@Autowiredprivate IAccountService service;@Testpublic void testTrans() throws Exception {service.trans(10086L,10010L,1000);}
}

App-Context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd" ><!-- DI注解解析器 --><context:annotation-config/><!-- IoC注解解释器 --><context:component-scan base-package="cn.wolfcode"/><bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!-- TX注解解释器 --><tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/><!-- 从classpath的根路径去加载db.properties文件 -->               <context:property-placeholder location="classpath:db.properties" system-properties-mode="NEVER"/><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driverClassName}"></property><property name="url" value="${jdbc.url}"></property><property name="username" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property><property name="initialSize" value="${jdbc.initialSize}"></property></bean></beans>
    1:切记在xml文件中配置   DataSourceTransactionManager  <bean>属性因为它是JDBC/MyBatis专属事务<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean>2:记得配置 TX 注解解析器<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>3:@Transactional()给需要使用事务的类配置,配置到类上表示类下面的所有方法都使用事务,()可以设置事务的属性@Transactional()配置到某个方法上,设置的属性,就覆盖所有类的事务属性,就可以单独设置,比如给查询方法设置只读@Transactional(readOnly=true)public void list(){}

6.使用Java-Config来做配置

service

//其余跟上面代码一样
@Service
@Transactional
public class AccountServiceImpl implements IAccountService{@Autowiredprivate IAccountDAO dao;public void trans(Long outId, Long inId, int money) {dao.transOut(outId, money);//int i = 3 / 0;dao.transIn(inId, money);}
}

AppConfig

//当前项目的配置类,好比是applicationContext.xml
@Configuration              //标志当前类为一个配置类
@Import(DataSourceConfig.class)//包含其他配置类
@ComponentScan              //IoC注解解析器   DI注解默认引入进来 不写的话从当前的包,包括子包都要扫描
@EnableTransactionManagement//事务注解解析器
public class AppConfig {//创建事务管理的Bean@Beanpublic DataSourceTransactionManager txManager(DataSource ds){return new DataSourceTransactionManager(ds);}
}

DataSourceConfig

//当前项目的连接池的配置类
@Configuration
@PropertySource("classpath:db.properties")
public class DataSourceConfig {@Value("${jdbc.driverClassName}")private String driverClassName;@Value("${jdbc.url}")private String url;@Value("${jdbc.username}")private String username;@Value("${jdbc.password}")private String password;@Value("${jdbc.initialSize}")private int initialSize;//创建连接池的Bean@Beanpublic DataSource dataSource(){DruidDataSource ds = new DruidDataSource();ds.setDriverClassName(driverClassName);ds.setUrl(url);ds.setUsername(username);ds.setPassword(password);ds.setInitialSize(initialSize);return ds;}
}

App

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=AppConfig.class)
public class App {@Autowiredprivate IAccountService service;@Testpublic void testTrans() throws Exception {service.trans(10086L,10010L,1000);}
}

Spring 框架 DAO 与 事务 的总结相关推荐

  1. Spring框架声明式事务管理

    Spring框架声明式事务管理 底层就是AOP原理,面向切面编程 在不修改源码的情况下,对方法进行增强 Spring框架事务管理相关类和API PlatformTransactionManager 平 ...

  2. Spring框架 声明式事务

    声明式事务 分类 ①编程式事务 由程序员来编写事务控制代码 ②声明式事务 事务控制代码已经由Spring完成,程序员只需声明那些方法进行事务控制和如何控制 特点 ①针对于ServiceImpl类下方法 ...

  3. spring框架复习--aop,事务

    AOP概述 1.AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. 2. 利用AOP可以对业务逻 ...

  4. 【spring】编程式事务控制

    结构: AccountServiceImpl package com.itheima.service.impl;import com.itheima.dao.IAccountDao; import c ...

  5. java 封装事务_Spring之路(36)–事务很重要吗?Spring为何要封装事务?Spring事务有陷阱吗?...

    可以不使用事务吗 真的遇到过开发企业应用,但是不知道啥是事务的朋友. 好吧,我始终认为抛开性能.界面.易用性等方面不说,正确性应该是一个项目最基础的要求了. 所以,凡是企业应用,正儿八经有客户的系统, ...

  6. Spring的七种事务传播行为

    一.什么是事务传播行为? 事务传播行为(propagation behavior)指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何运行. 例如:methodA方法调用methodB方 ...

  7. 【SSM框架系列】Spring - JdbcTemplate声明式事务

    JdbcTemplate概述 以往使用jdbc时,每次都需要自己获取PreparedStatement,执行sql语句,关闭连接等操作.操作麻烦冗余,影响编码的效率. Spring把对数据库的操作在j ...

  8. SSH框架之Spring4专题4:Spring与DAO

    本专题内容主要包含两部分:Spring所使用的操作数据库的技术之一,JDBC模版的使用:另一部分则为Spring对于事务的管理. Spring与Dao部分,是Spring的两大核心技术loC与AOP的 ...

  9. Spring框架-事务管理注意事项

    转载自 Spring框架-事务管理注意事项 常见事务问题 事务不起作用 可能是配置不起效,如扫描问题 事务自动提交了(批量操作中) 可能是在没事务的情况下,利用了数据库的隐式提交 事务配置说明 通常情 ...

最新文章

  1. 怎么把圆角变直角_明式圆角柜的还原(下)——信民木工DIY达人大赛作品
  2. Elasticsearch 5
  3. 网络营销——网络营销专员浅析网站推广营销关键词是重点
  4. Go if _,ok:=range map; ok判断key是否在map中
  5. nasm汇编:段的申明、$$、$
  6. 数据库-优化-子查询优化
  7. 分享套接字数据包序列化与反序列化方法
  8. android中绘图Paint.setAntiAlias()和Paint.setDither()方法的作用
  9. 游戏开发之类的构造函数调用时机(规则)及类对象作为另一个类的成员变量(C++基础)
  10. 【数据结构】KMP算法分析与理解(图文分析)
  11. 用 ElementTree 在 Python 中解析 XML
  12. java日期字符串排序_java字符串日期排序比较问题
  13. axure能做剪切蒙版吗_二手车销售好做吗?没经验能做二手销售吗?
  14. 51单片机60秒倒计时 数码管显示
  15. 消防设施操作员考试真题、模拟练习题库(7)
  16. 用python决定吃什么_如何决定今天吃什么?
  17. Android 带你玩转实现游戏2048 其实2048只是个普通的控件(转)
  18. 网络安全职业_我如何开始网络安全职业
  19. 计算机领域一般面试是会问到的各类常见算法的Big-O复杂度
  20. 计算机系统维护是干嘛,计算机系统维护是什么

热门文章

  1. linux进程跑飞了,【Shell】Linux信号(二)
  2. SPSS 限制检索个案
  3. Idea+springcloud+zookeeper做的服务发现和远程连接zookeeper
  4. java基础面试题之:String 类的常用方法都有那些?
  5. HandlerAdapter解析参数过程之HandlerMethodArgumentResolver
  6. C#:泛型(Generic)
  7. [luoguP3068] [USACO13JAN]派对邀请函Party Invitations(stl大乱交)
  8. Mac下python3配置Sklearn
  9. hadoop2.7.3+spark2.1.0+scala2.12.1环境搭建(4)SPARK 安装
  10. bzoj3202:[Sdoi2013]项链