前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >说吧,有没有被Spring事务坑过

说吧,有没有被Spring事务坑过

作者头像
灬沙师弟
发布2023-05-18 10:36:57
3260
发布2023-05-18 10:36:57
举报
文章被收录于专栏:Java面试教程

前言

新来的实习生找我吐槽,在开发过程中,经常遇到事务失效的问题,了不起实在看不下去了,整理了一份事务失效的N种情况,让他学习学习。

大纲

数据库引擎不支持事务

在MySQL5.5版本之前,默认的引擎是MyISAM,MyISAM引擎是不支持事务的。从MySQL5.5版本开始,默认引擎是InnoDB,InnoDB完全支持ACID原则和事务。所以当事务失效时,可以手动查询下当前数据库的存储引擎,具体的SQL语句如下:

代码语言:javascript
复制
SHOW VARIABLES LIKE 'default_storage_engine%';

类没有被Spring管理

代码语言:javascript
复制
// @Service
public class UserServiceImpl implements UserService {
    
    @Transactional
    public void saveUser(User user){
        // do something...
    }
}

对于上面的例子,类没有被@Service注解修饰,意味着当前类没有被Spring管理,事务自然就失效了。

方法的访问修饰符不是public

代码语言:javascript
复制
@Service
public class UserServiceImpl implements UserService {
    
    @Transactional
    protected void saveUser(User user){
        // do something...
    }
}

@Transactional注解只有修饰public方法时,事务才会生效,如果用在非public方法上,如protected、private,事务将失效。

自身调用问题

代码语言:javascript
复制
@Service
public class UserServiceImpl implements UserService {
    
    @Transactional
    public void saveUser(User user){
        // do something...
        updateUser(user);
    }
    
    @Transactional
    public void updateUser(User user){
        // do something...
    }
}

由于类发生了自身调用,即在saveUser方法中,使用了this.updateUser()进行方法调用,没有经过Spring的代理类,默认只有在外部调用事务方法时才生效。若程序存在自身调用且需要事务生效,可以通过获取代理类的方法进行调用,示例代码如下:

代码语言:javascript
复制
@Service
public class UserServiceImpl implements UserService {
    
    @Transactional
    public void saveUser(User user){
        // do something...
        ((UserService)AopContext.currentProxy()).updateUser(user);
    }
    
    @Transactional
    public void updateUser(User user){
        // do something...
    }
}

数据源没有配置事务管理器

数据源没有配置事务管理器时,事务将不生效,可通过以下方法进行配置。

代码语言:javascript
复制
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
}

不支持事务

代码语言:javascript
复制
@Service
public class UserServiceImpl implements UserService {
    
    @Transactional
    public void saveUser(User user){
        // do something...
        ((UserService)AopContext.currentProxy()).updateUser(user);
    }
    
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void updateUser(User user){
        // do something...
    }
}

当@Transactional注解使用了错误的传播机制,会导致事务失效。Propagation.NOT_SUPPORTED表示不以事务运行,当前若存在事务时则挂起。

异常被捕获

代码语言:javascript
复制
@Service
public class UserServiceImpl implements UserService {
    
    @Transactional
    public void saveUser(User user){
        try {
            // do something...
            int i = 1/0;
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}

当出现除0异常时,异常被catch捕获了,整个程序正常运行,没有抛出异常,最终导致事务无法回滚。

异常类型错误

代码语言:javascript
复制
@Service
public class UserServiceImpl implements UserService {
    
    @Transactional
    public void saveUser(User user){
     throw new Exception("save user error");
    }
}

@Transactional注解中,回滚的默认异常是RuntimeException,由于在saveUser()方法中抛出异常不是RuntimeException,导致当前事务不会回滚。若要使事务生效,建议使用@Transactional(rollbackFor = Exception.class)进行修饰。

总结

好啦,以上就是事务失效的几种常见的场景,不知道小伙伴们搞明白没有?在日常开发的过程中需要注意哦!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-05-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java面试教程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 大纲
  • 数据库引擎不支持事务
  • 类没有被Spring管理
  • 方法的访问修饰符不是public
  • 自身调用问题
  • 数据源没有配置事务管理器
  • 不支持事务
  • 异常被捕获
  • 异常类型错误
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档