百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 优雅编程 > 正文

mybatis插入获取主键的方式和原理

sinye56 2024-09-27 21:27 13 浏览 0 评论

1. 概述

很多时候我们在使用mybatis执行insert操作时,需要返回插入数据的主键信息,默认情况下是mybatis返回的是影响或者说符合过滤条件的行数,而不会返回主键信息,这是由jdbc驱动决定的。

jdbc默认情况下,执行update、delete或者insert操作,可以通过getUpdateCount()方法来获取更新、删除和插入的“行数”,其实这个行数不是真正的更新、删除和插入的行数,而是受到影响的行数,特别是update和delete,他们实际返回的是符合过滤条件的行数,如果要返回真实行数,需要设置jdbc链接参数:

useAffectedRows=true  #例如jdbc:mysql://192.168.231.7:3306/test?useAffectedRows=true

而mybatis正是调用了这个一个方法,作为update、delete和insert的返回值。既然返回值不是id,那如何获取插入数据的id呢?在mybatis中主要有三种方法。

说明:以下所说的都是针对mysql而言。

2. useGeneratedKeys方式

2.1 xml配置

通过在xml文件的insert标签中设置useGeneratedKeys和keyProperty两个属性,mybatis会自动将自增主键的值赋值到keyProperty设置的实体属性上。例如:

 <insert id="insert" parameterType="com.test.UserDO" useGeneratedKeys="true" keyProperty="catId">
     insert into user (name, age,address)
     values (#{name,jdbcType=CHAR}, #{age,jdbcType=INT},#{address,jdbcType=CHAR})
</insert>

设置步骤:

  • 设置useGeneratedKeys="true"
  • 设置keyProperty="xx",其中xx代表的是实体类对应的属性名称。

使用注意事项:

  • 必须是自增主键,不支持自增逐渐的数据库无法使用,例如oracle。

2.2 注解配置

除了通过xml方式配置,还可以通过注解方式配置,只需要在接口方法上添加@Options注解即可,配置如下:

@Options(useGeneratedKeys = true, keyProperty = "id")

完整配置如下:

@Insert("insert into test(xxx,xxx,xxx) values (xxx,xxx,xxx)")
@Options(useGeneratedKeys = true, keyProperty = "id")
void insert(TestDO testDO);

2.3 原理

当mybatis设置了useGeneratedKeys时,表示使用数据库的自增主键。在jdbc驱动程序中,Statement接口中(PreparedStatement也继承了Statement)有一个getGeneratedKeys方法,此方法将返回当前插入数据的自增主键。例如以下代码:

Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://192.168.231.7:3306/test","root","root");
Statement statement = connection.createStatement();
boolean res = statement.execute("INSERT INTO  user ( name, age,address) VALUES ('xiaoming3', 11,'北京海淀')",Statement.RETURN_GENERATED_KEYS);
ResultSet generatedKeys = statement.getGeneratedKeys();
while (generatedKeys.next()){
       System.out.println(generatedKeys.getInt(1));
    }

通过getGeneratedKeys获取主键的前提有两个:

  • 数据库必须是自增主键
  • 执行execute方法中必须添加Statement.RETURN_GENERATED_KEYS参数,否则程序将出现错误。

我们在使用useGeneratedKeys=true时,mybatis将使用Statement.RETURN_GENERATED_KEYS方式执行sql语句,然后将获取的ResultSet中的主键值赋值给我们指定的keyProperty变量。

3. selectKey+last_insert_id方式

3.1 xml配置

通过在insert标签中配置selectKey标签,执行select last_insert_id的方式来获取主键的配置如下:

<insert id="insert" parameterType="com.test.UserDO" useGeneratedKeys="true" keyProperty="catId">
    <selectKey keyProperty="catId" resultType="long" order="AFTER">
        select last_insert_id();
    </selectKey>
    insert into user (name, age,address)
     values (#{name,jdbcType=CHAR}, #{age,jdbcType=INT},#{address,jdbcType=CHAR})
</insert>

selectKey参数解释:

  • keyProperty:对应的实体类属性名称。
  • resultType:返回数据类型。
  • order:这个是一个非常关键的属性,表示和insert语句之间的执行顺序,order=“AFTER”,表示在执行insert语句后执行selectKey的内容,如果是BEFORE,则相反。

3.2 注解配置

通过注解方式配置如下:

@Insert("insert into test(xxx,xxx,xxx) values (xxx,xxx,xxx)")
@SelectKey(statement = "select last_insert_id()", keyProperty = "id", before = false, resultType = Long.class)
void insert(UserDO user);

参数说明:

  • statement:执行的sql语句。
  • keyProperty:实体类对应的属性。
  • before:这个属性和xml配置中的order作用一样,如果before等于false,表示先执行insert;否则表示先执行select。

3.3 原理

SelectKey方式的原理比较简单,它是使用了mysql的last_insert_id()函数。这个函数有两种使用方式,一种是无参数的,一种是有参数的。

如果此函数没有参数,表示一个连接使用AUTO_INCREMENT定义的列最近一次执行insert语句插入的第一个值。怎么理解这句话呢?

  • 如果一个连接是新建立的,使用一个连接执行一条insert操作,那么将返回插入的自增主键。
  • 如果一个连接是新建立的,使用一个连接同时执行多条insert插入(可以理解为一个事务中多个insert),那么返回的是第一个插入语句对应的自增主键。
  • 如果一个连接不是新建立的(我们一般使第三方数据源,c3p0或者druid等,这个时候是使用的连接池),如果你在程序中执行了insert,那么肯定是返回的肯定是最新插入一条的自增主键;如果你没有执行insert,而是直接执行了select last_insert_id,那么它将返回以前执行的最后一个插入的自增主键。
  • 还有一种情况,那就是一个连接,没有执行过任何操作,你直接使用它执行select last_insert_id,那么返回值是啥呢?官方文档说的是一个不可预测的值,但是通过实验,基本返回的都是0。

注意:主键必须是AUTO_INCREMENT。

具体的话可以参考官方文档,并按照官方文档上的说明进行实践操作。

[官方文档] https://dev.mysql.com/doc/refman/8.0/en/information-functions.html#function_last-insert-id

4. 自定义方式

自定义方式也是使用selectKey,不过获取主键的方式不再使用select last_insert_id,而是通过自定义的方式从数据库中获取主键,例如:你的表中记录了每个表的主键的最大值,每次插入的时候都需要从表中获取最新的id,然后执行插入。这种方式和上面的selectKey方式最大的不同是先执行select,获取到主键后在执行insert。只要把上面的配置稍微改动即可:

<insert id="insert" parameterType="com.test.UserDO" useGeneratedKeys="true" keyProperty="catId">
    <selectKey keyProperty="catId" resultType="long" order="AFTER">
        <![CDATA[ 这里变成获取主键的select语句 ]]>
    </selectKey>
    insert into user (id,name, age,address)
     values (#{id},#{name,jdbcType=CHAR}, #{age,jdbcType=INT},#{address,jdbcType=CHAR})
</insert>


不足之处,多多指教

相关推荐

程序员:JDK的安装与配置(完整版)_jdk的安装方法

对于Java程序员来说,jdk是必不陌生的一个词。但怎么安装配置jdk,对新手来说确实头疼的一件事情。我这里以jdk10为例,详细的说明讲解了jdk的安装和配置,如果有不明白的小伙伴可以评论区留言哦下...

Linux中安装jdk并配置环境变量_linux jdk安装教程及环境变量配置

一、通过连接工具登录到Linux(我这里使用的Centos7.6版本)服务器连接工具有很多我就不一一介绍了今天使用比较常用的XShell工具登录成功如下:二、上传jdk安装包到Linux服务器jdk...

麒麟系统安装JAVA JDK教程_麒麟系统配置jdk

检查检查系统是否自带java在麒麟系统桌面空白处,右键“在终端打开”,打开shell对话框输入:java–version查看是否自带java及版本如图所示,系统自带OpenJDK,要先卸载自带JDK...

学习笔记-Linux JDK - 安装&amp;配置

前提条件#检查是否存在JDKrpm-qa|grepjava#删除现存JDKyum-yremovejava*安装OracleJDK不分系统#进入安装文件目...

Linux新手入门系列:Linux下jdk安装配置

本系列文章是把作者刚接触和学习Linux时候的实操记录分享出来,内容主要包括Linux入门的一些理论概念知识、Web程序、mysql数据库的简单安装部署,希望能够帮到一些初学者,少走一些弯路。注意:L...

测试员必备:Linux下安装JDK 1.8你必须知道的那些事

1.简介在Oracle收购Sun后,Java的一系列产品就被整合到Oracle官网中,打开官网乍眼一看也不知道去哪里下载,还得一个一个的摸索尝试,而且网上大多数都是一些Oracle收购Sun前,或者就...

Linux 下安装JDK17_linux 安装jdk1.8 yum

一、安装环境操作系统:JDK版本:17二、安装步骤第一步:下载安装包下载Linux环境下的jdk1.8,请去官网(https://www.oracle.com/java/technologies/do...

在Ubuntu系统中安装JDK 17并配置环境变量教程

在Ubuntu系统上安装JDK17并配置环境变量是Java开发环境搭建的重要步骤。JDK17是Oracle提供的长期支持版本,广泛用于开发Java应用程序。以下是详细的步骤,帮助你在Ubuntu系...

如何在 Linux 上安装 Java_linux安装java的步骤

在桌面上拥抱Java应用程序,然后在所有桌面上运行它们。--SethKenlon(作者)无论你运行的是哪种操作系统,通常都有几种安装应用程序的方法。有时你可能会在应用程序商店中找到一个应用程序...

Windows和Linux环境下的JDK安装教程

JavaDevelopmentKit(简称JDK),是Java开发的核心工具包,提供了Java应用程序的编译、运行和开发所需的各类工具和类库。它包括了JRE(JavaRuntimeEnviro...

linux安装jdk_linux安装jdk软连接

JDK是啥就不用多介绍了哈,外行的人也不会进来看我的博文。依然记得读大学那会,第一次实验课就是在机房安装jdk,编写HelloWorld程序。时光飞逝啊,一下过了十多年了,挣了不少钱,买了跑车,娶了富...

linux安装jdk,全局配置,不同用户不同jdk

jdk1.8安装包链接:https://pan.baidu.com/s/14qBrh6ZpLK04QS8ogCepwg提取码:09zs上传文件解压tar-zxvfjdk-8u152-linux-...

运维大神教你在linux下安装jdk8_linux安装jdk1.7

1.到官网下载适合自己机器的版本。楼主下载的是jdk-8u66-linux-i586.tar.gzhttp://www.oracle.com/technetwork/java/javase/downl...

window和linux安装JDK1.8_linux 安装jdk1.8.tar

Windows安装JDK1.8的步骤:步骤1:下载JDK打开浏览器,找到JDK下载页面https://d.injdk.cn/download/oraclejdk/8在页面中找到并点击“下载...

最全的linux下安装JavaJDK的教程(图文详解)不会安装你来打我?

默认已经有了linux服务器,且有root账号首先检查一下是否已经安装过java的jdk任意位置输入命令:whichjava像我这个已经安装过了,就会提示在哪个位置,你的肯定是找不到。一般我们在...

取消回复欢迎 发表评论: