@transactional 事务注解注意事项
来源:互联网 发布:哪里有淘宝店铺转让 编辑:程序博客网 时间:2024/05/21 07:10
注解方式的事务使用注意事项
当您对 Spring 的基于注解方式的实现步骤和事务内在实现机制有较好的理解之后,就会更好的使用注解方式的事务管理,避免当系统抛出异常,数据不能回滚的问题。
正确的设置@Transactional 的 propagation 属性
需要注意下面三种 propagation 可以不启动事务。本来期望目标方法进行事务管理,但若是错误的配置这三种 propagation,事务将不会发生回滚。
- TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
- TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
- TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
正确的设置@Transactional 的 rollbackFor 属性
默认情况下,如果在事务中抛出了未检查异常(继承自 RuntimeException 的异常)或者 Error,则 Spring 将回滚事务;除此之外,Spring 不会回滚事务。
如果在事务中抛出其他类型的异常,并期望 Spring 能够回滚事务,可以指定 rollbackFor。例:
@Transactional(propagation= Propagation.REQUIRED,rollbackFor= MyException.class)
通过分析 Spring 源码可以知道,若在目标方法中抛出的异常是 rollbackFor 指定的异常的子类,事务同样会回滚。
清单 3. RollbackRuleAttribute 的 getDepth 方法
private int getDepth(Class<?> exceptionClass, int depth) {
if (exceptionClass.getName().contains(this.exceptionName)) {
// Found it!
return depth;
}
// If we've gone as far as we can go and haven't found it...
if (exceptionClass == Throwable.class) {
return -1;
}
return getDepth(exceptionClass.getSuperclass(), depth + 1);
}
@Transactional 只能应用到 public 方法才有效
只有@Transactional 注解应用到 public 方法,才能进行事务管理。这是因为在使用 Spring AOP 代理时,Spring 在调用在图 1 中的 TransactionInterceptor 在目标方法执行前后进行拦截之前,DynamicAdvisedInterceptor(CglibAopProxy 的内部类)的的 intercept 方法或 JdkDynamicAopProxy 的 invoke 方法会间接调用 AbstractFallbackTransactionAttributeSource(Spring 通过这个类获取表 1. @Transactional 注解的事务属性配置属性信息)的 computeTransactionAttribute 方法。
清单 4. AbstractFallbackTransactionAttributeSource
protected TransactionAttribute computeTransactionAttribute(Method method,
Class<?> targetClass) {
// Don't allow no-public methods as required.
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;}
这个方法会检查目标方法的修饰符是不是 public,若不是 public,就不会获取@Transactional 的属性配置信息,最终会造成不会用 TransactionInterceptor 来拦截该目标方法进行事务管理。
避免 Spring 的 AOP 的自调用问题
在 Spring 的 AOP 代理下,只有目标方法由外部调用,目标方法才由 Spring 生成的代理对象来管理,这会造成自调用问题。若同一类中的其他没有@Transactional 注解的方法内部调用有@Transactional 注解的方法,有@Transactional 注解的方法的事务被忽略,不会发生回滚。见清单 5 举例代码展示。
清单 5.自调用问题举例
@Service
-->public class OrderService {
private void insert() {
insertOrder();
}
@Transactional
public void insertOrder() {
//insert log info
//insertOrder
//updateAccount
}
}
insertOrder 尽管有@Transactional 注解,但它被内部方法 insert 调用,事务被忽略,出现异常事务不会发生回滚。
上面的两个问题@Transactional 注解只应用到 public 方法和自调用问题,是由于使用 Spring AOP 代理造成的。为解决这两个问题,使用 AspectJ 取代 Spring AOP 代理。
需要将下面的 AspectJ 信息添加到 xml 配置信息中。
清单 6. AspectJ 的 xml 配置信息
<
tx:annotation-driven
mode
=
"aspectj"
/>
<
bean
id
=
"transactionManager"
class
=
"org.springframework.jdbc.datasource.DataSourceTransactionManager"
>
<
property
name
=
"dataSource"
ref
=
"dataSource"
/>
</
bean
>
</
bean
class
=
"org.springframework.transaction.aspectj.AnnotationTransactionAspect"
factory-method
=
"aspectOf"
>
<
property
name
=
"transactionManager"
ref
=
"transactionManager"
/>
</
bean
>
同时在 Maven 的 pom 文件中加入 spring-aspects 和 aspectjrt 的 dependency 以及 aspectj-maven-plugin。
清单 7. AspectJ 的 pom 配置信息
<
dependency
>
<
groupId
>org.springframework</
groupId
>
<
artifactId
>spring-aspects</
artifactId
>
<
version
>4.3.2.RELEASE</
version
>
</
dependency
>
<
dependency
>
<
groupId
>org.aspectj</
groupId
>
<
artifactId
>aspectjrt</
artifactId
>
<
version
>1.8.9</
version
>
</
dependency
>
<
plugin
>
<
groupId
>org.codehaus.mojo</
groupId
>
<
artifactId
>aspectj-maven-plugin</
artifactId
>
<
version
>1.9</
version
>
<
configuration
>
<
showWeaveInfo
>true</
showWeaveInfo
>
<
aspectLibraries
>
<
aspectLibrary
>
<
groupId
>org.springframework</
groupId
>
<
artifactId
>spring-aspects</
artifactId
>
</
aspectLibrary
>
</
aspectLibraries
>
</
configuration
>
<
executions
>
<
execution
>
<
goals
>
<
goal
>compile</
goal
>
<
goal
>test-compile</
goal
>
</
goals
>
</
execution
>
</
executions
>
</
plugin
>
总结
通过本文的介绍,相信读者能够清楚的了解基于@Transactional 注解的实现步骤,能够透彻的理解的 Spring 的内部实现机制,并有效的掌握相关使用注意事项,从而能够正确而熟练的使用基于@Transactional 注解的事务管理方式。
- @transactional 事务注解注意事项
- spring 事务注解@Transactional
- spring 事务注解@Transactional
- spring 事务注解@Transactional
- Spring注解事务@Transactional
- Spring 注解@Transactional 事务
- SpringBoot事务注解@Transactional
- @Transactional 事务注解
- SpringBoot事务注解@Transactional
- @Transactional spring 配置事务 注意事项
- spring @Transactional 配置事务 注意事项
- @Transactional spring 配置事务 注意事项
- @Transactional spring 配置事务 注意事项
- @Transactional spring 配置事务 注意事项
- @Transactional spring 配置事务 注意事项
- @Transactional spring 配置事务 注意事项
- @Transactional spring 配置事务 注意事项
- Spring @Transactional注解使用注意事项
- pytorch 离线安装
- Qt之自定义控件(开关按钮)
- Java实现Spark程序中的坑坑洼洼
- 智能耳机究竟是智能还是智障
- 用surfaceView 做一个可动态变化的色环效果
- @transactional 事务注解注意事项
- 我要开始写博客啦 哈哈哈
- python 查看文档编码格式-chardet
- 解决mysql字段值为“default”时会被清空问题
- Spring实现控制反转(IOC)的三种方式(一)——属性注入
- 理解java回调机制
- 程序员的自我修养-路由交换原理
- err max number of clients reached 解决办法
- dubbo 源码学习笔记 (二) —— dubbo发布服务的过程