在SpringBoot2.x中使用使用需要注意的地方:
- 加@Transactional的方法不能是private和protected修饰,private会直接报编译错误,protected不会报错,但是事务不起作用;
- @Transactional可以放在Controller下面直接起作用;
- @Transactional有两个包:
import javax.transaction.Transactional
和import org.springframework.transaction.annotation.Transactional
,这两个都可以用,对比他们两个的方法和属性,发现后面的比前面的强大,建议后后面的; - PlatformTransactionManager这个接口中定义了三个方法
getTransaction创建事务
,commit 提交事务
,rollback 回滚事务
,实现类是 AbstractPlatformTransactionManager; - 在@Transactional这个中,有一个参数Propagation的属性,在它的七个类型中
REQUIRED
,REQUIRES_NEW
,NESTED
,这三个都是新建事务,其他的都不使用事务; - 当一个方法中嵌套使用@Transactional,如果没有设置属性 Propagation,默认为
REQUIRED
,只会在上下文创建一个事务,当设置属性为REQUIRES_NEW
的时候,会创建一个新的事务; - try&catch的使用,当一个事务中如果对异常进行了捕获,而且没有抛出异常的情况下,事务是不起作用的,只有抛出异常,事务会自己try&catch,然后进行回滚操作。
- @Transactional采用AOP实现,在调用方法时,发现这个方法有事务注解,AOP会检测到,然后用代理类采用反射机制进行调用:
- 首先调用了CglibAopProxy.intercept()方法
- 接下来调用ReflectiveMethodInvocation.proceed()方法
- TransactionInterceptor.invoke()
- TransactionAspectSupport.invokeWithinTransaction()
- TransactionAspectSupport.createTransactionIfNecessary()
- AbstractPlatformTransactionManager.getTransaction(),创建了一个新的事务。
- 问题注意:
异常捕获在Controller去做,这样在Service层中 @Transactional在发生异常时可以正常进行回滚操作;
如果使用Mysql数据库,需要注意创建表的引擎,支持InnoDD,默认创建表是 MyISAM;
如果配置了自动创建
,需要这样配置:
jpa:
hibernate:
ddl-auto: update
show-sql: true
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
一个栗子:
ServiceA.createTransaction()
参考:
https://www.cnblogs.com/baoyi/p/springboot_transactional.html
https://baike.baidu.com/item/JTA/9257852
https://www.oracle.com/technetwork/java/javaee/jta/index.html
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html