深入分析Mybatis 使用useGeneratedKeys获取自增主键 (2)

看下调用的方法 this.getGeneratedKeysInternal()

protected ResultSet getGeneratedKeysInternal() throws SQLException { // 获取影响的行数 int numKeys = this.getUpdateCount(); return this.getGeneratedKeysInternal(numKeys); }

这里有个重要知识点了,首先获取本次批量插入的影响行数,然后再执行具体的获取id操作。

getGeneratedKeysInternal方法

protected synchronized ResultSet getGeneratedKeysInternal(int numKeys) throws SQLException { Field[] fields = new Field[]{new Field("", "GENERATED_KEY", -5, 17)}; fields[0].setConnection(this.connection); fields[0].setUseOldNameMetadata(true); ArrayList rowSet = new ArrayList(); long beginAt = this.getLastInsertID(); // 按照受影响的范围+递增步长 for(int i = 0; i < numKeys; ++i) { if (beginAt > 0L) { // 值塞进去 row[0] = StringUtils.getBytes(Long.toString(beginAt)); } beginAt += (long)this.connection.getAutoIncrementIncrement(); } }

迭代影响的行数,然后依次获取id。

所以批量insert是正确可以返回的。
但是批量insertOrUpdate就有问题了,批量insertOrUpdate的影响行数不是插入的数据行数,可能是0,1,2这样就导致了自增id有问题了。

比如插入3条数据,2条会update,1条会insert,这时候updateCount就是5,generateid就会5个了,mybatis然后取前3个塞到数据里,显然是错的。

以上是原理分析,如果想了解更详细的实验结果,可以看下

总结 批量insert <insert useGeneratedKeys="true" keyProperty="id"> insert into Author (username, password, email, bio) values <foreach item="item" collection="list" separator=","> (#{item.username}, #{item.password}, #{item.email}, #{item.bio}) </foreach> </insert>

来自官网的例子,mapper中不能指定@Param参数,否则会有问题

批量insertOrUpdate

不能依赖useGeneratedKey返回主键。

关注公众号【方丈的寺院】,第一时间收到文章的更新,与方丈一起开始技术修行之路

在这里插入图片描述

参考

https://blog.csdn.net/slvher/article/details/42298355

https://blog.csdn.net/qq_27680317/article/details/81118070#%EF%BC%883%EF%BC%89%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5

https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-usagenotes-last-insert-id.html

https://dev.mysql.com/doc/refman/5.5/en/innodb-auto-increment-handling.html

https://dev.mysql.com/doc/refman/5.5/en/example-auto-increment.html

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyypyx.html