1.前言:一个bug没想到一个bug竟然来惹我两次!我可能沉迷于滚动。反正我是睡不着。我坐起来打开Mac和外接显示器。这个错误没有任何原因。我默默地看着打印异常的屏幕。一个是我的,另一个也是我的。今天这个问题主要体现在大家平时使用的Mybatis上。插入数据时,我们可以通过入参对象返回库表索引的返回值。但是通过我自己手写的Mybatis,每次都返回0,而不是最后一次插入库表的索引值。因为是手写的,并没有直接使用Mybatis,所以我会从文件解析、对象映射、SQL查询、结果打包等方面继续排查,但是问题不就在这里吗?!这是selectKey的配置。执行完insertSQL,开始执行得到最终的索引值。通常只要配置正确,返回对象中有对应的id字段,就可以正确获取到返回值。PS:问题就在这里,付哥手写的Mybatis居然只返回一个0!2、分析:大部分研发小伙伴可能没有看过Mybatis的源码进行异常诊断,所以可能不知道这里发生了什么。这里付哥给大家画个图,告诉大家到底发生了什么,使得返回结果为0。。Mybatis的处理过程可以分为两部分,一部分是解析,一部分是使用。解析时,解析出MapperXML中的insert标签语句,同时解析selectKey标签。最后解析完成后,使用MappedStatement映射语句类存储解析出的语句信息。可以从Configuration配置项中获取,用于DefaultSqlSession中的后续操作。然后这里有很重要的一点,就是执行insert的时候,还包含了一个query操作。也就是说,我们会在一个Insert中包含两条执行语句。关键点:bug就发生在这里,为什么?因为一开始执行这两条语句的时候,在获取链接的时候,每一个都获取一个新的链接,所以也就是说insertxxx和selectLAST_INSERT_ID()在执行两个connection连接的时候其实是错误的。是的,获取不到插入后的索引ID。只有在一个链接或者一个事务(一次commit)下,才有事务特性,才能得到插入数据后的自增ID。又因为这部分先手写JdbcTransaction实现Transaction接口获取连接,每次都是新建一个链接,代码块如下;这里的链接获取,一开始的时候,没有一开始的ifnull判断,每次都是直接获取链接,所以这不是一个链接下的两个sql操作,所以不会获取到正确的结果,是相当于只单独执行SELECTLAST_INSERT_ID(),所以最终查询结果为0!你可以测试将这条语句复制到SQL查询工具中执行。3.震惊:同样的坑居然就这么一个链接问题,小傅手写Spring也遇到过。Spring的一部分是关于事务处理的。其实这些事务操作也是JDBC封装操作,依靠从数据源获取的链接来管理事务。而我们平时使用Spring结合Mybatis配置数据源的方式,那么我们如何在一个事务下操作多条SQL语句时得到同一个链接。因为从上面
