您现在的位置是:亿华云 > 人工智能
线上问题事迹(一)数据库事务居然都没生效?
亿华云2025-10-03 11:52:21【人工智能】7人已围观
简介Spring声明式事务提供给 Javaer 们方便的事务配置方式,再搭配Spring Boot自动配置,基本只需在方法上添加@Transactional注解,即可瞬间开启方法的事务性配置。但仅为方法添
Spring声明式事务提供给 Javaer 们方便的线上效事务配置方式,再搭配Spring Boot自动配置,问题务居基本只需在方法上添加@Transactional注解,事迹数据即可瞬间开启方法的库事事务性配置。
但仅为方法添加@Transactional注解
你就以为这就够了吗?然都
事务未被正确处理,一般不会导致停止服务,没生更不易在测试阶段复现。线上效但随系统业务越来越复杂,问题务居就会带来大量数据不一致问题,事迹数据随后就是库事大量线上问题而后人工排查检修数据。
1 你的然都Spring事务怎么才算生效?
使用@Transactional开启声明式事务时, 灵魂发问:事务生效了吗?没生
案例
用户表实体类

DAO 层
根据username查询所有数据
@Repository public interface UserRepository extends JpaRepository<UserEntity, Long> { List<UserEntity> findByName(String name); }Service层
UserService类
负责业务逻辑处理,包括如下方法:
createUserWrong1调用private方法:
createUserPrivate,线上效被@Transactional注解。问题务居当传入的事迹数据用户名包含test则抛异常,让用户的创建操作失败,期望事务回滚:

getUserCount

Controller层
调用一下刚才定义的UserService中的入口方法createUserWrong1。

测试结果
即便用户名不合法,用户也能创建成功。刷新浏览器,多次发现非法用户注册。
2 @Transactional怎么确保生效?
除非特殊配置(比如使用AspectJ静态织入实现AOP),否则只有定义在public方法上的@Transactional才能生效。
Spring默认通过动态代理实现AOP,对目标方法增强,高防服务器private方法无法代理到,自然也无法动态增强事务处理逻辑。
那简单,把createUserPrivate方法改为public即可。
在UserService中再建一个入口方法createUserWrong2,来调用这个public方法再次尝试:
public int createUserWrong2(String name) { try { this.createUserPublic(new UserEntity(name)); } catch (Exception ex) { log.error("create user failed because { }", ex.getMessage()); } return userRepository.findByName(name).size(); } //标记了@Transactional的public方法 @Transactional public void createUserPublic(UserEntity entity) { userRepository.save(entity); if (entity.getName().contains("test")) throw new RuntimeException("invalid username!"); }新的createUserWrong2方法事务同样不生效。
必须通过代理过的类从外部调用目标方法
要调用增强过的方法必然是调用代理后的对象。
尝试修改UserService,注入一个self,然后再通过self实例调用标记有@Transactional注解的createUserPublic方法。设置断点可以看到,self是由Spring通过CGLIB方式增强过的类。
CGLIB通过继承方式实现代理类,private方法在子类不可见,自然也就无法进行事务增强;
this指针代表对象自己,Spring不可能注入this,所以通过this访问方法必然不是代理。
把this改为self,在Controller中调用createUserRight方法可以验证事务生效了:非法的用户注册操作可以回滚。
虽然在UserService内部注入自己调用自己的createUserPublic可以正确实现事务,但这不符合习惯用法。香港云服务器更合理的实现方式是,让Controller直接调用之前定义的UserService的createUserPublic方法。
@GetMapping("right2") public int right2(@RequestParam("name") String name) { try { userService.createUserPublic(new UserEntity(name)); } catch (Exception ex) { log.error("create user failed because { }", ex.getMessage()); } return userService.getUserCount(name); }this自调用/self调用/Controller调用UserService

无法走到Spring代理类
后两种调用的Spring注入的UserService,通过代理调用才有机会对createUserPublic方法进行动态增强。
推荐在开发时打开相关Debug日志,以了解Spring事务实现的细节。
比如JPA数据库访问,可以这么开启Debug日志:
logging.level.org.springframework.orm.jpa=DEBUG
开启日志后再比较下在UserService中this调用、Controller中通过注入的UserService Bean调用createUserPublic的区别。
很明显,this调用因没走代理,事务没有在createUserPublic生效,只在Repository的save生效:
// 在UserService中通过this调用public的createUserPublic [23:04:30.748] [http-nio-45678-exec-5] [DEBUG] [o.s.orm.jpa.JpaTransactionManager:370 ] - Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT [DEBUG] [o.s.orm.jpa.JpaTransactionManager :370 ] - Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT //在Controller中通过注入的UserService Bean调用createUserPublic [10:10:47.750] [http-nio-45678-exec-6] [DEBUG] [o.s.orm.jpa.JpaTransactionManager :370 ] - Creating new transaction with name [org.geekbang.time.commonmistakes.transaction.demo1.UserService.createUserPublic]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT这种实现在Controller里处理异常显得繁琐,还不如直接把createUserWrong2加@Transactional注解,然后在Controller中直接调用该方法。
这既能从外部(Controller中)调用UserService方法,方法又是public的能够被动态代理AOP增强。要不你试试?看看效果如何,下回分解~
亿华云很赞哦!(74425)
相关文章
- 协同运力、算力、存力,加速迈向智能世界
- 2、定期提交和投标域名注册。例如,益华网络点击“立即预订”后,平台会抢先为客户注册域名。当然,一个域名可能会被多个客户预订,所以出价最高的人中标。
- 当投资者经过第二阶段的认真学习之后又充满了信心,认为自己可以在市场上叱咤风云地大干一场了。但没想到“看花容易绣花难”,由于对理论知识不会灵活运用.从而失去灵活应变的本能,就经常会出现小赢大亏的局面,结果往往仍以失败告终。这使投资者很是困惑和痛苦,不知该如何办,甚至开始怀疑这个市场是不是不适合自己。在这种情况下,有的人选择了放弃,但有的意志坚定者则决定做最后的尝试。
- 3、考虑出售域名
- 戴尔科技安全解决方案 帮助用户拒绝勒索软件攻击
- 在更换域名后,并不是就万事大吉了,我们需要将旧域名做301重定向到新域名上,转移旧域名的权重到新域名上。
- 4、企业无形资产:通用网站已成为企业网络知识产权的重要组成部分,属于企业的无形资产,也有助于提升企业的品牌形象和技术领先形象。它是企业品牌资产不可或缺的一部分。
- 4、club娱乐
- 智简DC,绿建未来!华为发布下一代数据中心
- .net 适用于从事Internet相关的网络服务的机构或公司
热门文章
站长推荐
免费1年服务器,部署个ChatGPT专属网页版!
什么是im域名?新手需要了解im域名哪些?
4、域名传输时,取决于域名原始用户的邮箱是否有效,以及他是否将密码发送到此邮箱。
当投资者经过第二阶段的认真学习之后又充满了信心,认为自己可以在市场上叱咤风云地大干一场了。但没想到“看花容易绣花难”,由于对理论知识不会灵活运用.从而失去灵活应变的本能,就经常会出现小赢大亏的局面,结果往往仍以失败告终。这使投资者很是困惑和痛苦,不知该如何办,甚至开始怀疑这个市场是不是不适合自己。在这种情况下,有的人选择了放弃,但有的意志坚定者则决定做最后的尝试。
量旋科技项金根:坚持“双轮驱动”战略,加速量子计算产业化和普惠化
6、提示添加成功,点击确认进行最后的确定操作。一般10分钟就解析生效,可以用域名进行访问了。
注册域名要了解几大点?新手有什么方式注册域名?
并非一个好米任何人都会给你一个好的价格。那你该如何用以有的好米卖出最理想的价格呢?