mybatis uuid主键 auto_increment列 回显id keyGenerator

背景

我们的系统是使用的tk.mybatis,原来线上的一个表用的uuid主键。来了一个业务需求,需要新增一个自增的索引列(ALTER TABLEtestADD COLUMNuniq_indexBIGINT AUTO_INCREMENT UNIQUE COMMENT '自增索引';

增加了这个列之后,调用insert(object)插入方法,会将传入的对象的id回显(object.id=自增id);

然而,我们期望的是回显主键uuid(线上逻辑),但是实际上回显的是自增id,不符合需求,会导致bug。

参考作者的文档

https://github.com/mybatis-book/book/issues/45

单步调试

从insert开始一步一步地往里走
在这里插入图片描述

在这里插入图片描述

应该就是这个后置处理的时候会回写id
在这里插入图片描述
回头看发现是这里产生的generatedkey
在这里插入图片描述

通过参考作者写的文档:https://github.com/abel533/Mapper/wiki/2.3-generatedvalue

我们发现生成的key有一个优先级顺序

我们原先是用的是一个类来实现,是最低优先级的。
在这里插入图片描述
使用这种key生成方法,会在我们不传入key的情况下,自动用我们指定的类来生成id。
但是,这种方法,会导致我们在有一个自增id的列的情况下,会把自增id填充到我们insert传入的对象的id,这个其实是不符合预期的,我们还是希望返回的id是uuid的id。

为了解决这个问题,参考上面的文档,可以做下面的注解,使用sql语句在插入前生成一个uuid,然后作为key插入。这样就可以解决上述的问题。
在这里插入图片描述

在这里插入图片描述

使用新的配置之后,会在prepareStatement的时候,利用我们配置sql查询到uuid,作为id用于插入数据库

在这里插入图片描述

然后进入一个好深的调用栈,最终调用我们定义的sql语句获取id
在这里插入图片描述

如果是原来的配置为啥就会把id给改了,是哪里导致代码执行逻辑不一致呢?
我们把配置改回原来的样子:使用自定义的类生成id
在这里插入图片描述

再单步调试走一遍
发现keyGenerator不是一样的:
在这里插入图片描述

找到凶手!
在这里插入图片描述
当我们走这个配置genId=xxx.class的时候,keyGenerator是 Jdbc3KeyGenerator 这个在processBefore函数里啥也不干;在processAfter函数里会调用populateKeys,将id给覆盖掉!

当我们走配置@KeySql(sql = "select REPLACE(uuid(),'-','')", order = ORDER.BEFORE) 的时候, keyGenerator是selectKeyGenerator,而他的processAfter函数就不会有populateKeys这种逻辑,所以就不会把id覆盖掉了~
在这里插入图片描述

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章