spring事务失效场景
2023-06-08 22:01:46 0 举报
AI智能生成
Spring事务失效场景通常发生在以下几种情况:1. 方法没有被Spring管理,即没有使用@Transactional注解;2. 异常类型不符合预期,例如在捕获了RuntimeException类型的异常后,事务仍然会回滚;3. 数据库引擎不支持事务,例如MyISAM;4. 手动提交事务或者在事务外部修改了数据;5. 多线程环境下,同一个事务被多个线程同时访问。
作者其他创作
大纲/内容
访问权限问题
private
default
protected
方法用final修饰
@Service
public class EmpService {
@Transactional
public final void add(UserModel userModel){
saveData(userModel);
}
}
public class EmpService {
@Transactional
public final void add(UserModel userModel){
saveData(userModel);
}
}
因为spring事务底层是用了aop,用了jdk的动态代理或者cglb的动态代理,会帮我们生成代理类,在代理类中实现事务功能。
如果某个方法被final修饰了,那么在代理类中,就无法重新该方法,而添加事务功能
如果某个方法被final修饰了,那么在代理类中,就无法重新该方法,而添加事务功能
多线程管理
@Service
public class EmpService {
@Autowired
private OrderService orderService;
@Transactional
public void add(UserModel userModel){
new Thread(()->{
orderService.updateSataus();
}).start();
}
}
@Service
public class OrderService{
@Transactional
public void updateSataus(){
System.out.println("======================");
}
}
public class EmpService {
@Autowired
private OrderService orderService;
@Transactional
public void add(UserModel userModel){
new Thread(()->{
orderService.updateSataus();
}).start();
}
}
@Service
public class OrderService{
@Transactional
public void updateSataus(){
System.out.println("======================");
}
}
事务保存在当前线程的treadlocal中,如果是多线程的话就是多个threadlocal,线程之间相互隔离,自然多线程事务是失效的
手动抛了别的异常
@Service
public class EmpService {
@Transactional
public void add(UserModel userModel) throws Exception {
try {
saveData(userModel);
updateSataus(userModel);
} catch (Exception e) {
throw new Exception(e);
}
}
}
public class EmpService {
@Transactional
public void add(UserModel userModel) throws Exception {
try {
saveData(userModel);
updateSataus(userModel);
} catch (Exception e) {
throw new Exception(e);
}
}
}
因为Spring事务,默认情况下只会回滚RuntimeException(运行时异常)和Error(错误),对于普通的非运行时异常,它不会回滚
数据库不支持事务
inodb支持事务
myisam不支持事务
类未被spring容器管理
public class EmpService {
@Transactional
public void add(UserModel userModel){
saveData(userModel);
updateSataus(userModel);
}
}
@Transactional
public void add(UserModel userModel){
saveData(userModel);
updateSataus(userModel);
}
}
事务是基于spring容器管理的,如果没有被spring容器管理,事务自然会失效
直接调用内部方法
@Service
public class EmpService {
@Transactional
public void add(UserModel userModel){
saveData(userModel);
updateSataus(userModel);
}
@Transactional
public void updateSataus(UserModel userModel){
doSomething();
}
}
public class EmpService {
@Transactional
public void add(UserModel userModel){
saveData(userModel);
updateSataus(userModel);
}
@Transactional
public void updateSataus(UserModel userModel){
doSomething();
}
}
由上可知:在事务方法add可知,它直接调用了updateStatus方法,由2可知:方法拥有事务的能力是因为spring aop中生成了代理对象,但是直接调用updateStatus方法不会直接生成事务。但是可以直接将该类直接注入进来,比如
@Service
public class EmpService {
private EmpService empService;
@Transactional
public void add(UserModel userModel){
saveData(userModel);
empService.updateSataus(userModel);
}
@Transactional(rollbackFor = Exception.class)
public void updateSataus(UserModel userModel){
doSomething();
}
}
public class EmpService {
private EmpService empService;
@Transactional
public void add(UserModel userModel){
saveData(userModel);
empService.updateSataus(userModel);
}
@Transactional(rollbackFor = Exception.class)
public void updateSataus(UserModel userModel){
doSomething();
}
}
调用本类的方法(this代表了是本类对象调用,而不是从容器中获取到代理对象去调用)
事务未开启
如果是springBoot项目,那么是事务默认是开启的,但如果是spring项目,需要xml配置
方法的传播类型不支持事务
如果事务的传播特性设置错了,事务也会失效。如下:propagation = Propagation.NEVER这种类型的传播特性不支持事务,如果有事务会抛出异常。
目前只有这三种传播特性才会创建新事物:REQUIRED、REQUIRES_NEW、NESTED
目前只有这三种传播特性才会创建新事物:REQUIRED、REQUIRES_NEW、NESTED
@Service
public class EmpService {
@Transactional(propagation = Propagation.NEVER)
public void add(UserModel userModel){
saveData(userModel);
updateSataus(userModel);
}
}
public class EmpService {
@Transactional(propagation = Propagation.NEVER)
public void add(UserModel userModel){
saveData(userModel);
updateSataus(userModel);
}
}
自己吞了异常没有交给事务
@Service
public class EmpService {
@Transactional
public void add(UserModel userModel){
try {
saveData(userModel);
updateSataus(userModel);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class EmpService {
@Transactional
public void add(UserModel userModel){
try {
saveData(userModel);
updateSataus(userModel);
} catch (Exception e) {
e.printStackTrace();
}
}
}
事务不会回滚,最常见的问题是:开发者在代码中手动try...catch了异常。如下:
0 条评论
下一页