Spring中事务管理
事务的概念不过多介绍,聊聊Spring中的事务,本文中AOP理解成拦截器
首先事务管理可以帮助我们保证数据的一致性以及准确性,所以事务管理重要性不言而喻
Spring的事务机制包括声明式事务和编程式事务。
编程式事务管理:Spring推荐使用TransactionTemplate,实际开发中使用声明式事务较多。
声明式事务管理:(依靠AOP)将我们从复杂的事务处理中解脱出来,获取连接,关闭连接、事务提交、回滚、异常处理等这些操作都不用我们处理了,Spring都会帮我们处理。
声明式事务管理使用了AOP面向切面编程实现的,本质就是在目标方法执行前后进行拦截。在目标方法执行前加入或创建一个事务,在执行方法执行后,根据实际情况选择提交或是回滚事务。
Spring提供了是三个接口供管理事务
TransactionDefinition :事务定义信息–用来定义事务相关的属性,给事务管理器PlatformTransactionManager使用,有四个主要的方法:
getIsolationLevel:获取隔离级别;(与Mysql隔离级别一致,未提交读,已提交读,可重复读,可串行化)
getPropagationBehavior:获取传播行为;
propagation:用于指定事务的传播行为,默认值是REQUIRED:表示一定会有事务,增删改的选择。查询方法可以选择SUPPORTS
getTimeout:获取超时时间;
isReadOnly:是否只读(保存、更新、删除时属性变为false–可读写,查询时为true–只读)
事务管理器能够根据这个返回值进行优化,这些事务的配置信息,都可以通过配置文件进行配置。
PlatformTransactionManager:事务管理器
commit(TransactionStatus) //提交事务
rolback(TransactionStatus) //回滚事务
getTranscation(TransactionDefinition) //传入事务的定义信息,获取事务
TransactionStatus :事务的运行状态
hasSavepoint(); …
**
事务的迷之失效
**
1.使用默认处理方式处理异常
@Transaction()
不加任何参数,当发生异常时,spring默认只有RuntimeException和Error才可以回滚,而其他的异常spring默认它们都已经处理,所以默认不回滚。可以添加rollbackfor=Exception.class来表示所有的Exception都回滚。包括其子类
@Transaction(rollbackfor=Exception.class)
2.内部调用
不带事务的方法调用该类中带事务的方法,不会回滚。因为spring的回滚是用过代理模式生成的,如果是一个不带事务的方法调用该类的带事务的方法,直接通过this.xxx()调用,而不生成代理事务,所以事务不起作用。
当然在spring中在一个拥有事务的方法X中调用另一个会挂起事务并创建新事务的方法Y,如果使用this调用这个方法Y, 此时方法Y抛出了一个异常,此时的方法Y的事务会失效的。
JDK的动态代理。只有被动态代理直接调用时才会产生事务。在SpringIoC容器中返回的调用的对象是代理对象而不是真实的对象。this调用是真实类的对象,而不是代理对象
有两个方法防止失效
1.在方法X上开启事务,方法Y不用事务或默认事务,并在方法X的catch中throw new RuntimeException(); //注意是RuntimeException异常上文提及过
@Transactional() //开启事务
public void X(){
try {
this.Y(); //这里this调用会使事务失效
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException();
}
}
2.方法X上可以不开启事务,方法Y上开启事务,并在方法X中将this调用改成动态代理调用AopContext.currentProxy()
public void X(){
try {
EmployeeService proxy =(EmployeeService) AopContext.currentProxy();
proxy.Y();//用当前代理对象调用Y
}catch (Exception e){
e.printStackTrace();
}
}