作者:小傅哥 博客:https://bugstack.cn
❝沉淀、分享、成长,让自己和他人都能有所收获!😜 ❞
没想到一个Bug,竟然搞我两次!
我大抵是卷上瘾了,横竖都睡不着,坐起来身来打开Mac和外接显示器,这Bug没有由来,默然看着打印异常的屏幕,一个是我的,另外一个也是我的。
最近可能是卷源码,卷上瘾了。先是《手写Spring》,再是《手写Mybatis》,但没想到一个小问题竟然搞了我2次!
今天这个问题主要体现在大家平常用的Mybatis,在插入数据的时候,我们可以把库表索引的返回值通过入参对象返回回来。但是通过我自己手写的Mybatis,每次返回来的都是0,而不是最后插入库表的索引值。因为是手写的,不是直接使用Mybatis,所以我会从文件的解析、对象的映射、SQL的查询、结果的封装等一直排查下去,但竟然问题都不在这?!
可能大部分研发伙伴没有阅读过 Mybatis 源码,所以可能不太清楚这里发生了什么,小傅哥这里给大家画张图,告诉你发生了什么才让返回的结果为0的。
SELECT LAST_INSERT_ID()
所以最终的查询结果为 0 了就!你可以测试把这条语句复制到 SQL查询工具中执行😂 但其实就这么一个链接的问题,在小傅哥手写Spring中也同样遇到过。
在 Spring 中有一部分是关于事务的处理,其实这些事务的操作也是对 JDBC 的包装操作,依赖于数据源获得的链接来管理事务。而我们通常使用 Spring 也是结合着 Mybatis 配置上数据源的方式进行使用,那么在一个事务下操作多个 SQL 语句的时候,是怎么获得同一个链接的呢。因为从上面👆🏻的案例中,我们得知保证事务的特性,需要在同一个链接下,即使是操作多条SQL
由于多个SQL的操作,已经是相当于每次都获取一个新的 Session 有一个新的链接从连接池中获得,但为了能达到事务的特性,所以在需要有事务操作下的多个 SQL 前需要开启事务操作,无论是手动还是注解。
而这个事务的开启动作处理做一些事务传播行为和隔离级别的限制,其实更重要的是让多个 SQL 的执行获取的链接,需要是同一个。所以这里就引入了 ThreadLocal 基于它在同一个线程操作下保存信息的同步特性,其实这里的从事务下获取的链接,其实就是保存到 TransactionSynchronizationManager#resources 属性中的。
虽然就这么一小块内容,但在小傅哥最开始手写Spring的时候,也是给漏下了。直到到测试的时候,才发现链接发现事务总是不成功,最初还以为是整个切面逻辑没有切进去或者是我的操作方式有误。直到逐步排查调试代码,发现原来多个SQL的执行竟然不是获得的同一个链接,所以也就没法让事务生效。
可能就是这么一个小小的链接问题,有时候就会引起一堆的异常,如果说我们没有学习过源码,那么可能也不知道这样的问题到底是如何发生的。所以往往深入的研究和探索,才能让你解释一个问题的时候,更加简单直接。
那么你说,事务失效的原因还有哪些?- 分享一些常见,如果你还有遇到其他的,可以发到评论区一起看看。
// @Service - 这里被注释掉了 public class OrderServiceImpl implements OrderService { @Transactional public void placeOrder(Order order) { // ... } }
@Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); }
@Transactional(rollbackFor = Exception.class)
很多类似这样的技术问题,都是来自于小傅哥对源码的学习,最开始是遇到问题的时候去翻看源码,虽然很多时候也很难把整个逻辑捋顺,但一点点的积累确实会让研发人员对技术有更加夯实的认知。
那么在现在我之所以去手写Spring、手写Mybatis,也是希望通过把这样的知识全部整理处理,从中学习复杂逻辑的设计方案、设计原则和如何运用设计模式解决复杂场景的问题。PS:通常我们的业务代码复杂度很难到这个程度,所以在见过”天“后,以后所承接的业务就很容易做设计了。
另外就是对各类技术细节的把控,以及积累于这样的经验把相关技术设计运用到一些类似 SpringBoot Starter 等的开发,只有类似这样的广度、高度、深度,才能真的把个人的研发能力提升起来。PS:也是为了在技术的路上走的更远,无论是高级开发、架构师、CTO!
欢迎一起学习手写源码和实战项目! 适合:有需要校招、面试、晋升,想提高自己的技术深度,为自己的职业生涯续期,可以长稳发展,完善自己的技术体系,奔着高级开发和架构师路线的研发伙伴。
校招、面试、晋升,加入小傅哥的私有技术朋友圈!
- END -