Mybatis是如何生成自增主键的id给对象呢

Mybatis是如何生成自增主键的id给对象呢

  1. 前天遇到了一个问题,需求场景是这样的:系统中有两张表:一张车辆主表和车辆设备信息表,设备信息表中关联车辆主表的主键ID。系统做了一个EXCEL批量导入车辆及设备信息的功能,在测试服务器上测试没有问题,但是上正式环境后,发生了一个奇怪的现象:车辆信息和设备信息对应不上了,有窜行现象(比如第一台车辆对应第二个车辆设备)。于是开始艰难的查找问题之路。
  2. 首先想到可能的问题是不是他们上传时,excel的格式不对?于是乎找了一份正式的文件,看了一下,文件确实存在问题。告知他们修改文件的格式及表头。本以为这是小问题,已经解决。下午又给反馈,还是不行。。(what!?一定是你们操作方式不对!)。于是亲自上正式环境导入一次,艹!果然不对。。啪啪打脸。。
  3. 于是再次分析想,难道是导入excel之后,数据插入之前的处理有问题?漏掉了了某一条数据?于是打出日志,对比excel解析后的数据和入库之前的数据,发现还是匹配的上的,并没有什么问题!这tm心态就崩了呀。。这什么情况!??于是绞尽脑汁接着想。。那查查数据库吧。
  4. 由于登录正式环境,需要用跳板机,老不方便,查看数据库还需要使用命令行,所以一般不愿意查询数据库。没办法,只能查看一下数据了。通过sql一查询,完蛋,主键id是不连续的,每个id中间都隔了1。通过命令show variables like '%auto_increment_increment%'查看发现,主键自增步长为2,于是把这个变量设置成1,问题解决。问题原因似乎找到了:插入数据库,使用的是mybatis批量插入。第一步插入车辆信息,插入成功后,主键id返回到车辆实体类中,然后将车辆的id,赋值给设备信息实体类的车辆id字段,然后再批量插入设备信息。伪代码:
   carDao.batchInsert(saveCars);//批量保存车辆
   for (int i = 0; i <saveCars.size() ; i++) {
            CarInfo car= saveCars.get(i);
            DeviceInfo deviceInfo= saveDevices.get(i);
            deviceInfo.setCarId(car.getId());
        }
   deviceDao.batchInsert(saveDevices);//批量保存设备

批量插入用的mybatis。例如插入10台车辆信息,返回的id是1,2,3…10,然后将车辆id赋值给设备,应该是没问题的。可是问题就出在这里:由于数据库设置的自增步长是2,导致数据库中的id是不连续的,实际数据库中车辆id是1,3,5,7。。。19。但是,mybatis拿到的却是连续的id,也就是1,2,3,4…10.然后赋值给设备。
在这里插入图片描述数据库中设备信息记录的车辆id是一一对应的,正常查询第二行车辆id为2的设备(此时id连续),应该是查到设备b

实际情况数据库记录:
在这里插入图片描述
此时,列表列出的车辆信息是5台,现在要查询第二行车辆,也就是id为3的车辆的设备信息(此时id已经不连续)。结果查询到的设备,是设备表第三行的设备,也就是设备c,此时发生了窜行,数据对不上了。
5. 那么问题来了,为什么mybatis插入数据成功后,拿到的id为什么和数据库中实际的id不一致呢?于是想到了看一下,看一下id是如何赋值的。经过多轮debug,终于找到赋值的地方,大致的调用过程:

1.processBatch(MappedStatement ms, Statement stmt, Object parameter)
  -->2. assignKeys(configuration, rs, rsmd, keyProperties, parameter);
     -->3.assignKeysToParam(configuration, rs, rsmd, keyProperties, parameter);
       -->4.assignerList.forEach(x -> x.assign(rs, param));
         --5.Object value = typeHandler.getResult(rs, columnPosition);
         	   metaParam.setValue(propertyName, value);
  在第5步时候,调用的是--int result = rs.getInt(columnIndex);
  也就是从结果集中获取id.

在这里插入图片描述去处理赋值
在这里插入图片描述从结果集中获取id,然后通过反射赋值。
6. 看到最后,按照我的理解,插入成功后,是从结果集中获取主键id,然后反射赋值给对象。可是,我的疑问依然没解决:讲道理结果集中的id应该就是数据库中的id,对象中的主键,应该和数据库中的id一致,可是为什么数据库中如果自增长步长是2,数据库中记录的主键是1,3,5,7…,而mybatis中赋值给对象的,确实1,2,3,4呢。。
求哪位大佬指教。。抱拳!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值