您现在的位置是:首页 >学无止境 >jpa事务失效的 场景网站首页学无止境
jpa事务失效的 场景
简介jpa事务失效的 场景
jpa默认只有抛出RuntimeException,才会回滚,
1.异常被捕获
//不回滚
public void delete(String id) {
try {
ptInterInfoDao.deleteById(id);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
这个catch只是输出了异常信息,并没有抛出,不会发生回滚,要把异常抛出,才会回滚
//回滚
public void delete(String id) {
try {
ptInterInfoDao.deleteById(id);
} catch (Exception e) {
System.out.println(e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
2. 方法不是public
@Transactional注解只有修饰public方法时,事务才会生效,如果用在非public方法上,如protected、private,事务将失效。
3. 没有被Spring管理
类上面没有spring的注解,意味着当前类没有被Spring管理,事务自然就失效了。
4. 异常类型错误
@Transactional注解中,回滚的默认异常是RuntimeException,由于在saveUser()方法中抛出异常不是RuntimeException,导致当前事务不会回滚。若要使事务生效,使用@Transactional(rollbackFor = Exception.class)指定类型。
@Service
public class UserServiceImpl implements UserService {
@Transactional
public void saveUser(User user){
throw new Exception("save user error");
}
}
5. 自身调用问题
@Transactional的实现原理是AOP,而AOP的实现原理是动态代理,自己调用自己的过程,并不存在代理对象的调用,这样
就不会产生AOP去为我们设置@Transactional配置的参数,这样就出现了自调用注解失效的问题。
@Service
public class Test3 {
@Transactional
public void test1(){
test2();
}
public void test2(){
System.out.println(1/0);
}
}
解决方法:
- 把自己注入进来,然后通过注入的对象调用方法
6. 传播类型不支持事务,导致事务失效
/以非事务方式运行
@Transactional(propagation Propagation.NOT_SUPPORTED)
Propagation.NOT SUPPORTED:表示不以事务运行,当前若存在事务则挂起,都主动不支持以事务方式运行了,那事务肯定就不生效了
7. 多线程调用,导致事务失效
两个方法不在同一个线程中,获取到的数据库连接不一样,从而是两个不同的事务。我们说的同一个事务,其实是指同一个数据库连接,只有拥有同一个数据库连接才能同时提交和回滚。如果在不同
的线程,拿到的数据库连接肯定是不一样的,所以是不同的事务。
8. 数据表本身是不支持事务,导致事务失效
如果使用MySQL且存储引擎是MyISAM,则事务是不起作用的,原因是MyIASM不支持事务。
数据表可以改为InnoDB存储引擎,支持事务
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。