日常踩坑_添加了@Transactional注解后,事务不生效
故事梗概
事情是这样的,在使用Jpa的saveAll方法的时候,发现saveAll方法会进行先查询后保存的操作,但我只想要保存,不想要查询
关于saveAll的重写 可以这样用
@PersistenceContext private EntityManager em; @Override public <T> void saveAll(Iterable<T> entities) { for (T entity : entities) { em.persist(entity); } em.flush(); em.clear(); }
完成了重写之后,发现数据存不进去,而且报错了:No EntityManager with actual transaction available for current thread
这个报错的原因是没有加事务,其实我在saveAll方法上加了@Transactional
注解的,但是并没有生效
一般的@Transactional
不生效的原因
1、检查你的方法是不是public的,@Transactional注解只能应用到public可见度的方法上,如果应用在protected、private或者package可见度的方法上,也不会报错,不过事务设置不会起作用。
2、检查你的异常类型是不是unchecked异常。默认情况下,Spring会对unchecked异常进行事务回滚,如果是checked异常则不回滚。如空指针异常、算术异常等,会被回滚;文件读写、网络出问题,spring就没法回滚了。如果你想check异常也回滚怎么办,注解上面写明异常类型即可:
like this
@Transactional(rollbackFor = Exception.class)
3、是否在service中进行了try...catch的操作,由于已经被捕获异常,故事务也不会回滚。如果非要在service中try...catch异常,又想要事务回滚,可在catch块中抛出运行时异常
try{ .... }catch(Exception e){ logger.error("",e); throw new RuntimeException; }
这种方法有个不足之处,就是不能在catch块中存在return子句,若想捕获异常时回滚事务,同时返回提示信息,可以使用手动回滚:
try{ ... }catch(Exception e){ logger.error("",e); TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); return ERROR_MESSAGE; }
PS:另外说明一下,在controller层捕获了service层的异常,事务还会回滚吗?答案是会的,只要你service层抛出了异常,并且你加的事务可以处理这个异常,也就是rollbackFor = Exception.class这个符合你抛出的异常,不管外面有没有捕获都可以回滚。
4、是否开启了对注解的解析:
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
5、数据库引擎要支持事务,如果是mysql,注意表要使用支持事务的引擎,比如innodb,如果是myisam,事务是不起作用的。
6、spring是否扫描到你这个包,如下是扫描到org.test下面的包:
<context:component-scan base-package="org.test" ></context:component-scan>
解决
对我来说,以上都没用,哈哈
真实的原因是,@Transactional没加对地方,我把它加在了saveAll的方法上,但实际上我在save()方法中调用了一个create()方法,create()方法中才调用了saveAll()方法
诸位,看清这个关系 save()->create()->saveAll()
那么@Transactional应该加在主方法save()上,而不是下面被调用的方法中
原因是事务可传递,Spring 的事务传播策略在内部方法调用时将不起作用,事务注解加到要调用方法上
ps:注意@Transactional
也不要加在接口上,因为spring 采用 aop 针对具体实现类做的代理实现
跳坑完毕,祝你快乐!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~