1. 编程式事务

通过手动编写代码来实现事务。在编程式事务中有以下几个重要的接口:

  • TransactionDefinition:定义了Spring兼容的事务属性(比如事务隔离级别、事务传播、事务超时、是否只读状态)
  • TransactionStatus:代表了事务的具体运行状态(获取事务运行状态的信息,也可以通过该接口间接提交回滚事务等操作)
  • PlatformTransactionManager:事务管理器接口(定义了一组行为,具体实现交由不同的持久化框架来完成—-类比JDBC)

    2. 声明式事务

    声明式事务因为封装了大量的东西(一般我们使用简单,里头都非常复杂),所以声明式事务实现要难得多。在声明式事务中,除了TransactionStatus和PlatformTransactionManager接口,还有几个重要的接口:

  • TransactionProxyFactoryBean:生成代理对象

  • TransactionInterceptor:实现对象的拦截
  • TransactionAttrubute:事务配置的数据
  • TransactionAspectSupport:创建事务

    2.3. 声明式事务失效的场景

  1. @Transactional注解应用在非public修饰的方法上
  2. @Transactional的propagation属性设置错误
  3. @Transactional的属性rollbackFor设置错误
  4. 同一个类方法中被没有@Transactional修饰的方法调用,导致@Transactional失效
  5. 异常被catch捕获,导致@Transactional回滚失效
  6. 数据库引擎不支持事务

    3. 传播行为

    注意:不能同类中调用,否则传播行为基本失效

  7. REQUIRED

    • 如果当前有事务就在当前事务运行,否则创建一个新的事务,并在创建的当前事务运行
  8. REQUIRES_NEW
    • 必须开启新的事务,并在创建的当前事务运行,如果之前有事务,那么应该将之挂起
  9. NESTED
    • 如果当前有事务,就在当前事务的嵌套事务中运行,否则创建一个新的事务,并在创建的当前事务运行
    • 嵌套的事务依托于外部事务,外部出异常,嵌套的也会回滚;内部出异常会影响外部的事务
  10. SUPPORTS
    • 如果有事务就在事务中运行,否则也可以不在事务中运行
  11. NOT_SUPPORTED
    • 当前方法不应该运行在事务中,如果有事务应该将它挂起
  12. NEVER
    • 当前方法不应该运行在事务中,如果有事务,会抛出异常
  13. MANDATORY
    • 当前方法必须运行在事务中,否则直接抛出异常
  • NESTED和REQUIRED、REQUIRES_NEW的区别
    1. @Transactional
    2. public String getEntity() {
    3. txService.testUpdate(); //传播行为是REQUIRED_NEW
    4. txService.testDelete(); //传播行为是NESTED
    5. System.out.println(1/0); //第一行不回滚,第二行回滚:因为与外层事务是一个嵌套事务
    6. }
    1. @Transactional
    2. public String getEntity() {
    3. txService.testUpdate(); //传播行为是REQUIRED_NEW
    4. txService.testDelete(); //传播行为是REQUIRED
    5. System.out.println(1/0); //第一行不会滚,第二行回滚:因为与外层事务是同一个事务
    6. }