Mybatis之KeyGenerator

KeyGenerator简介

默认情况下,insert语句并不会返回自动生成的主键,而是返回插入记录的条数。如果业务逻辑需要获取插入记录时产生的自增主键,则可以使用Mybatis提供的KeyGenerator接口。不同的数据库产品对应的主键生成策略不一样,例如,Oracle、DB2等数据库产品是通过 sequence 实现自增 id 的,在执行insert语句之前必须明确指定主键的值;而MySQL、Postgresql等数据库在执行insert 语句时,可以不指定主键,在插入过程中由数据库自动生成自增主键。KeyGenerator接口针对这些不同的数据库产品提供了对应的处理方法,KeyGenerator接口的定义如下

public interface KeyGenerator {
    
    // 在执行insert之前执行,设置属性order="BEFORE"
    void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter);

    // 在执行insert之前执行,设置属性order="AFTER"
    void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter);

}

Mybatis提供了三个KeyGenerator接口的实现,如下图所示

KeyGenerator用法

Jdbc3KeyGenerator
<insert id="addComment" useGeneratedKeys="true" keyProperty="id">
    insert into `comment`(`blog_id`, `content`) values (#{blogId},#{content})
</insert>

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

keyProperty : 指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。

SelectKeyGenerator用法

mysql用法示例

<insert id="addComment">
    <selectKey keyProperty="id" order="AFTER" resultType="int">
        select LAST_INSERT_ID()
    </selectKey>
    insert into `comment`(`blog_id`, `content`) values (#{blogId},#{content})
</insert>

oracle用法示例

<insert id="addComment">
    <selectKey keyProperty="id" order="BEFORE" resultType="int">
      select SEQ_COMMENT.nextval from dual
    </selectKey>
    insert into "comment" ("id","blog_id","content") values (#{id},#{blogId},#{content})
</insert>

SelectKey最终也会被解析成一个MappedStatement,它就相当于主Sql的一个关联Sql,我们需要关注order值是AFTER,还是BEFORE,它表示关联Sql是在主Sql之前执行,还是之后执行

当然SelectKey也不局限与上述用法,比如我们使用UUID做主键

<insert id="addComment">
    <selectKey keyProperty="id" order="BEFORE" resultType="string">
        select UUID()
    </selectKey>
    insert into `comment`(`id`,`blog_id`, `content`) values (#{id},#{blogId},#{content})
</insert>

LAST_INSERT_ID

LAST_INSERT_ID()

在没有参数的情况下,LAST_INSERT_ID()返回一个BIGINT UNSIGNED(64位)值,该值表示最近执行的INSERT语句为AUTO_INCREMENT列成功插入的第一个自动生成的值。如果没有成功插入任何行,LAST_INSERT_ID()的值(默认0)将保持不变。

LAST_INSERT_ID()具有以下特点 : 

作用域限制 : 生成的ID在服务器中按每个连接进行维护。这意味着函数返回给给定客户端的值是为该客户端影响AUTO_INCREMENT列的最新语句生成的第一个AUTO_INCREMENT值。此值不受其他客户端的影响,即使它们生成自己的AUTO_INCREMENT值也是如此。这种行为确保每个客户端都可以检索自己的ID,而不必关心其他客户端的活动,也不需要锁或事务。

非事务限制 : LAST_INSERT_ID()不受事务影响,即使ROLLBACK,LAST_INSERT_ID()的值不会恢复到事务之前的值

PS : 如果使用单个insert语句插入多行,LAST_INSERT_ID()将仅返回为插入的第一行生成的值。
LAST_INSERT_ID(expr)

如果将expr作为参数提供给LAST_INSERT_ID(),则函数将返回该参数的值,并将其记为LAST_INSERT_ID()返回的下一个值。用法示例如下:

源码简析

XMLStatementBuilder#parseStatementNode

通过源码我们知道,mybatis会先解析selectKey标签,如果存在selectKey标签,则使用SelectKeyGenerator。如果SqlCommand是INSERT,并且useGeneratedKeys为true,则使用Jdbc3KeyGenerator。默认使用NoKeyGenerator

processBefore执行时机

 KeyGenerator的processBefore方法是在构建StatementHandler对象的时候执行的

processAfter执行时机

KeyGenerator的processAfter方法是在执行完更新操作后执行的 

小结

对于Mybatis来说,SelectKeyGenerator会执行两次查询,效率上低于Jdbc3KeyGenerator

相关推荐

  1. Mybatis缓存

    2024-04-22 08:54:03       34 阅读
  2. MyBatis动态Sql

    2024-04-22 08:54:03       37 阅读
  3. MyBatis缓存

    2024-04-22 08:54:03       29 阅读
  4. MyBatis关联查询

    2024-04-22 08:54:03       34 阅读
  5. mybatis动态SQL

    2024-04-22 08:54:03       25 阅读
  6. MybatisSqlSession详解

    2024-04-22 08:54:03       37 阅读
  7. MybatisSqlSessionFactory详解

    2024-04-22 08:54:03       44 阅读
  8. Mybatis什么是Mybatis框架

    2024-04-22 08:54:03       35 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-22 08:54:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-22 08:54:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-22 08:54:03       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-22 08:54:03       20 阅读

热门阅读

  1. linux apt-get安装Jenkins

    2024-04-22 08:54:03       13 阅读
  2. HarmonyOS NEXT中怎么理解HAR、HAP、HSP、App的关系

    2024-04-22 08:54:03       27 阅读
  3. leetcode905-Sort Array By Parity

    2024-04-22 08:54:03       10 阅读
  4. OEACLE的instr和instrb 例子

    2024-04-22 08:54:03       14 阅读
  5. Rust基本数据类型-字符串

    2024-04-22 08:54:03       13 阅读
  6. ElasticSearch 创建索引超时(ReadTimeoutError)

    2024-04-22 08:54:03       15 阅读
  7. react ts react-router 6路由配置

    2024-04-22 08:54:03       10 阅读
  8. jni,android

    2024-04-22 08:54:03       13 阅读
  9. 小米K8s运维-云原生方向(面经分享)

    2024-04-22 08:54:03       10 阅读
  10. HIVE:谓词下推

    2024-04-22 08:54:03       10 阅读
  11. 关于面向对象与面向过程的基本概念

    2024-04-22 08:54:03       13 阅读
  12. Github 2024-04-21 开源项目日报 Top10

    2024-04-22 08:54:03       13 阅读