https://www.bilibili.com/video/av47952931
p75-78
几个点:
- JavaEE体系进行分层开发,事务处理位于业务层
 
- Spring提供事务控制的接口,在spring-tx-5.0.2.RELEASE.jar中
 
- Spring的事务控制基于AOP。它既可以用配置方式实现,也可以用编程方式实现(重点是配置实现)
 
Spring中事务控制的API
该接口提供事务操作的方法:
- 获取状态 getTransaction()
 
- 提交 commit()
 
- 回滚 rollback()
 
常用实现类:
- org.springframework.jdbc.datasource.DataSourceTransactionManager 
 
- org.springframework.orm.hibernate5.HibernateTransactionManager 
 
TransactionDefinition
该接口是事务的定义信息对象,可以获取事务对象名称、隔离级别、传播行为、超时时间、是否只读
Spring默认使用数据库的隔离级别
传播行为指什么情况下必须有事务、什么情况可有可无
TransactionStatus
该接口提供事务的运行状态,可以刷新事务、获取是否存在存储点(可以理解为按步提交,回滚可以回滚到当前点,不用全部回滚)、是否完成、是否为新的事务、是否回滚、设置回滚
Spring的事务控制
代码准备
pom.xml中需要导入aspectj的依赖,因为事务控制基于AOP
准备数据库表和实体类(还是账户)
实现三个方法:根据Id查询账户、根据名称查询账户、转账
编写Dao层和业务层接口和实现类
基于XML的声明式事务控制
配置步骤
1、配置事务管理器
2、配置事务的通知
此时需要导入事务的约束(文档首页点Data Access,搜xmlns:tx,同时也会导入AOP的约束)
使用tx:advice标签配置事务通知
属性:id:事务通知的唯一标识   transaction-manager:给事务通知提供一个事务管理器引用
3、配置AOP中的通用切入点表达式
4、建立事务通知和切入点表达式的对应关系
5、配置事务的属性(在事务的通知tx:advice标签的内部)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
   |  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">   <property name="dataSource" ref="dataSource"></property> </bean>
 
  <tx:advice id="txAdvice" transaction-manager="transactionManager">   
 
 
 
 
 
 
    <tx:attributes>     <tx:method name="*" propagation="REQUIRED" read-only="false"/>          <tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method>   </tx:attributes> </tx:advice>
 
  <aop:config>      <aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"></aop:pointcut>      <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor> </aop:config>
 
  | 
 
这样service.impl下的实现类就都配置好事务控制了
基于注解的声明式事务控制
导名称空间时要多一个context,以及对应的约束
业务层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
   | @Service("accountService") @Transactional(propagation= Propagation.SUPPORTS,readOnly=true)  public class AccountServiceImpl implements IAccountService{
      @Autowired     private IAccountDao accountDao;
      public Account findAccountById(Integer accountId) {         return accountDao.findAccountById(accountId);
      }
           @Transactional(propagation= Propagation.REQUIRED,readOnly=false)     public void transfer(String sourceName, String targetName, Float money) {                          Account source = accountDao.findAccountByName(sourceName);                          Account target = accountDao.findAccountByName(targetName);                          source.setMoney(source.getMoney()-money);                          target.setMoney(target.getMoney()+money);                          accountDao.updateAccount(source);
              int i=1/0;
                           accountDao.updateAccount(target);     } }
  | 
 
Dao层
1 2 3 4 5 6 7 8 9
   | @Repository("accountDao") public class AccountDaoImpl implements IAccountDao {
      @Autowired     private JdbcTemplate jdbcTemplate;          
  }
  | 
 
此时不能再继承JdbcDaoSupport了(因为没法给jdbcTemplate加注解),必须自己定义一个jdbcTemplate,并在xml中配置(并注入dataSource,还要配置Spring在创建容器时需要扫描的包)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
   |  <context:component-scan base-package="com.itheima"></context:component-scan>
 
  <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">   <property name="dataSource" ref="dataSource"></property> </bean>
 
  <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">   <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>   <property name="url" value="jdbc:mysql://localhost:3306/eesy"></property>   <property name="username" value="root"></property>   <property name="password" value="1234"></property> </bean>
 
 
 
 
 
 
  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">   <property name="dataSource" ref="dataSource"></property> </bean>
 
  <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
 
  | 
 
属性在@Transactional中配置
一个问题是,如果有十个事务,一半只读一半读写,就都得单独配置属性
而用xml配置时一次就解决了