MyBatis 这小子是怎样拿到 insert 时生成的主键的?

简介: SQL 语句执行insert,这谁都会,执行之后,返回结果是影响行数。但是在我们应用开发场景中,有些表的主键采用自增生成。这个时候,你怎么能把这个自增的主键值拿到呢?你说这还不简单,马上再执行一下select,就都查出来啦。

SQL 语句执行insert,这谁都会,执行之后,返回结果是影响行数。但是在我们应用开发场景中,有些表的主键采用自增生成。这个时候,你怎么能把这个自增的主键值拿到呢?

你说这还不简单,马上再执行一下select,就都查出来啦。 你的where是什么才限定刚好是新增的那一条呢? 你说,那我查主键值最大的那一条呢? 也不灵。毕竟insert和select之间是有时间差的,此时可能有其他写入操作。

一些常用的 ORM 框架在执行完save操作之后,一般都会把新生成的主键自动回填到PO对象中。那它们是怎么做到的呢?

带着这个疑问,咱们一起来看一下,时下活跃在各大应用中的明星MyBatis

MyBatis 是如何取到自增主键值的

我们知道, MyBatis 无论通过注解,还是XML配置的形式,将待执行的SQL包装起来,在执行时通过代理进行解析。

我们分析过MyBatis的大致执行原理,为何只写一个接口就能映射到一个XML或者注解中对应的SQL逻辑上

其中有个类MappedStatement,我们在XML里配置的各类SQL 都会转成这样一个实例。这个类中包含了大量配置相关的信息。

我们摘一段代码来看看:

 

代码比较长,咱们长话短说,重点看这一句

这里根据配置时指定是否使用UseGeneratedKeys来决定生成的keyGenerator实例是谁。

咱们使用时,在 XML 里的 insert 一般写成这样:

这个时候, insert 这个 XML 标签包含的一些配置就会使用默认值,其中有一个配置项就是咱们上面在MappedStatement中看到的useGeneratedKeys。它的默认值是false。也就是说,这种配置情况下,这个插入操作的自增主键并不会回写回来。

这个配置主要作用:

(仅对 insert 和 update 有用)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系数据库管理系统的自动递增字段),默认值:false。

那咱们把它改成true,同时把自增的列和对应的PO里的属性名写上就可以了。再执行一次操作,在insert 之后, PO 里对应的主键就已经自动填充了。

他是在哪一步做的呢?

MyBatis 如何从 XML的方法映射到 SQLCommand,然后从SQLCommand 的SQLType 再执行不同的操作这些,咱们不细说,具体INSERT,也会执行到PreparedStatementHandler类中的这个update方法。

 

请留意KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();这一句,就是咱们在创建mappedStatement时,根据 useKeyGenerator配置生成的。

在keyGenerator.processAfter方法中,会有一个操作。这里的keyGenerator是根据配置来决定的,如果没有配置useGeneratedKeys=true的话,那这里返回的就是NoKeyGenerator,配置的话,则返回Jdbc3KeyGenerator

位于 Jdbc3KeyGenerator类中, 我们看到,还是继续持有执行SQL的 Statement,然后 通过执行其getGeneratedKeys方法,来拿到一些数据。

重点就是这一句:rs = stmt.getGeneratedKeys();。

Java 文档里描述如下:

Retrieves any auto-generated keys created as a result of executing thisStatementobject. If thisStatementobject did not generate any keys, an emptyResultSetobject is returned.

和我们在前面看到对于useGeneratedKeys的说明描述一致,即通过JDBC API 的方法来拿到自增生成的值,在拿到rs,也就是标准的 JDBC ResultSet 之后,操作和一般的JDBC一样,通过读取columnName来取值。所以我们在前面配置的地方,也需要加上keyColumn。

这就是 MyBatis 获取自增主键的全部秘密。


欢迎工作一到五年的Java工程师朋友们加入Java填坑之路:860113481
群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!
 

相关文章
|
7月前
|
Java 数据库连接 mybatis
Mybatis Plus保存数据返回主键id
Mybatis Plus保存数据返回主键id
288 1
|
2月前
|
SQL Java 数据库连接
Mybatis的<insert>,<update>,<delete>标签用法
这篇文章详细讲解了Mybatis中<insert>, <update>, <delete>标签的使用方法,并提供了示例代码来展示如何执行数据库的增删改操作。
57 0
|
3月前
|
SQL XML Java
mybatis :sqlmapconfig.xml配置 ++++Mapper XML 文件(sql/insert/delete/update/select)(增删改查)用法
当然,这些仅是MyBatis功能的初步介绍。MyBatis还提供了高级特性,如动态SQL、类型处理器、插件等,可以进一步提供对数据库交互的强大支持和灵活性。希望上述内容对您理解MyBatis的基本操作有所帮助。在实际使用中,您可能还需要根据具体的业务要求调整和优化SQL语句和配置。
54 1
|
5月前
|
Java 数据库连接 测试技术
mybatis plus 获取新增实体的主键
mybatis plus 获取新增实体的主键
155 8
|
5月前
|
算法 Java 数据库连接
mybatis plus 主键策略
mybatis plus 主键策略
56 2
|
5月前
|
Oracle 关系型数据库 Java
mybatis使用statement.getGenreatedKeys(); useGeneratedKeys=”true”;使用自增主键获取主键值策略和Oracle不支持自增,Oracle使用序列
mybatis使用statement.getGenreatedKeys(); useGeneratedKeys=”true”;使用自增主键获取主键值策略和Oracle不支持自增,Oracle使用序列
|
6月前
|
SQL Java 数据库连接
2万字实操案例之在Springboot框架下基于注解用Mybatis开发实现基础操作MySQL之预编译SQL主键返回增删改查
2万字实操案例之在Springboot框架下基于注解用Mybatis开发实现基础操作MySQL之预编译SQL主键返回增删改查
78 2
|
7月前
|
SQL Oracle 关系型数据库
整合Mybatis-Plus高级,Oracle 主键Sequence,Sql 注入器实现自定义全局操作
整合Mybatis-Plus高级,Oracle 主键Sequence,Sql 注入器实现自定义全局操作
149 0
|
6月前
|
关系型数据库 MySQL 数据库
mysql 中文问号,mybatis-plus insert中文数据库显示问号
mysql 中文问号,mybatis-plus insert中文数据库显示问号
64 1
|
7月前
|
SQL 存储 算法
Mybatis-Plus- CRUD接口-主键策略-自动填充和乐观锁-分页-逻辑删除-条件构造器和常用接口
Mybatis-Plus- CRUD接口-主键策略-自动填充和乐观锁-分页-逻辑删除-条件构造器和常用接口