1. 概述
本文,我们来分享 SQL 执行的第三部分,keygen
包。整体类图如下:
- 我们可以看到,整体是以 KeyGenerator 为核心。所以,本文主要会看到的就是 KeyGenerator 对自增主键的获取。
2. KeyGenerator
org.apache.ibatis.executor.keygen.KeyGenerator
,主键生成器接口。代码如下:
KeyGenerator 有三个子类,如下图所示:
3. Jdbc3KeyGenerator
org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator
,实现 KeyGenerator 接口,基于 Statement#getGeneratedKeys()
方法的 KeyGenerator 实现类,适用于 MySQL、H2 主键生成。
3.1 构造方法
3.2 processBefore
@Override public void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
|
- 空实现。因为对于 Jdbc3KeyGenerator 类的主键,是在 SQL 执行后,才生成。
3.3 processAfter
- 调用
#processBatch(Executor executor, MappedStatement ms, Statement stmt, Object parameter)
方法,处理返回的自增主键。单个 parameter
参数,可以认为是批量的一个特例。
3.4 processBatch
<1>
处,获得主键属性的配置。如果为空,则直接返回,说明不需要主键。
- 【重要】
<2>
处,调用 Statement#getGeneratedKeys()
方法,获得返回的自增主键。
<3>
处,调用 #getSoleParameter(Object parameter)
方法,获得唯一的参数对象。详细解析,先跳到 「3.4.1 getSoleParameter」 。
<4>
处,关闭 ResultSet 对象。
3.4.1 getSoleParameter
-
<1>
处,如下可以符合这个条件。代码如下:
@Options(useGeneratedKeys = true, keyProperty = "id") @Insert({"insert into country (countryname,countrycode) values (#{country.countryname},#{country.countrycode})"}) int insertNamedBean(@Param("country") Country country);
|
-
<2>
处,如下可以符合这个条件。代码如下:
@Options(useGeneratedKeys = true, keyProperty = "country.id") @Insert({"insert into country (countryname, countrycode) values (#{country.countryname}, #{country.countrycode})"}) int insertMultiParams_keyPropertyWithWrongParamName2(@Param("country") Country country, @Param("someId") Integer someId);
|
- 虽然有
country
和 someId
参数,但是最终会被封装成一个 parameter
参数,类型为 ParamMap 类型。为什么呢?答案在 ParamNameResolver#getNamedParams(Object[] args)
方法中。
- 如果是这个情况,获得的主键,会设置回
country
的 id
属性,因为注解上的 keyProperty = "country.id"
配置。
- ?? 此处比较绕,也相对用的少。
-
<3>
处,如下可以符合这个条件。代码如下:
@Options(useGeneratedKeys = true, keyProperty = "id") @Insert({"insert into country (countryname, countrycode) values (#{country.countryname}, #{country.countrycode})"}) int insertMultiParams_keyPropertyWithWrongParamName3(@Param("country") Country country);
|
- 相比
<2>
的示例,主要是 keyProperty = "id"
的修改,和去掉了 @Param("someId") Integer someId
参数。
- 实际上,这种情况,和
<1>
是类似的。
- 三种情况,
<2>
和 <3>
有点复杂,胖友实际上,理解 <1>
即可。
3.4.2 assignKeysToParam
3.4.3 assignKeysToOneOfParams
<1>
处,需要有 .
。例如:@Options(useGeneratedKeys = true, keyProperty = "country.id")
。
<2>
处,获得真正的参数值。
<3>
处,获得主键的属性的配置。
<4>
处,调用 #assignKeysToParam(...)
方法,设置主键们,到参数 param
中。所以,后续流程,又回到了 「3.4.2」 咧。
- 关于这个方法,胖友自己模拟下这个情况,调试下会比较好理解。?? 当然,也可以不理解,嘿嘿。
3.5 populateKeys
4. SelectKeyGenerator
org.apache.ibatis.executor.keygen.SelectKeyGenerator
,实现 KeyGenerator 接口,基于从数据库查询主键的 KeyGenerator 实现类,适用于 Oracle、PostgreSQL 。
4.1 构造方法
4.2 processBefore
- 调用
#processGeneratedKeys(...)
方法。
4.3 processAfter
- 也是调用
#processGeneratedKeys(...)
方法。
4.4 processGeneratedKeys
4.5 示例
5. NoKeyGenerator
org.apache.ibatis.executor.keygen.NoKeyGenerator
,实现 KeyGenerator 接口,空的 KeyGenerator 实现类,即无需主键生成。代码如下:
mybatis-KeyGenerator
原文:https://www.cnblogs.com/siye1989/p/11624144.html