(六) MyBatis从入门到入土——主键的获取

Wesley13
• 阅读 561

这是mybatis系列第六篇。没看前文的建议先去【Java冢狐】公众号中查看前文,方便理解和掌握。

前面五篇把MyBatis的基本用法基本介绍完毕了,强烈推荐大家先把前面五篇看完实际操作完再来看接下来的内容。

增删改返回值说明

mybatis中对db执行增删改操作,不管是新增、删除、还是修改,其本质都是使用jdbc中对应的方法,即java.sql.Statement的executeUpdate的方法,或者java.sql.PreparedStatement的executeUpdate方法。

所以问题的关键在于掌握这两个方法的内容,而这两个方法的参数不一致但是返回值都是int,用来表示影响的行数。

而Mybatis的返回值再支持int的基础上,还支持Integer、long、Long、boolean、Boolean、void多种类型,可谓是大大加强了编程的灵活性和多样性。

但是聪明的小伙伴肯定知道,MyBatis能支持这么多种的类型,其实就是mybatis在内部将int类型转换成其他类型而已。没有什么高深的东西、

了解了增删改查的返回值后,下一步我们再去看一看jdbc和mybatis是如何获取主键的。

jdbc获取主键的几种方式

在聊jdbc获取主键的方式之前,我们先来回想一下数据库的主键是怎么样生成的。

那mysql举例:在mysql中当我们向表中插入数据的时候,如果不指定主键(id),那么mysql会自动生成id,但是在一些业务中我们后续会需要这个id,此时我们就要想办法去获取这个id,尤其是这种自动生成的自增id。

要想要清楚的了解,就需要先看看jdbc是如何实现的

方式1:jdbc内置的方式

用法

获取主键的需求,jdbc的开发人员就已经想到了,并且也开发了相应的api来帮助我们编程,具体看 java.sql.Statement类中的getGeneratedKeys方法

从这个方法中我们得知这个方法会返回一个结果集,从这个结果集中可以获取自增主键的值。但是在使用这个方法有个前提,那就是执行sql的时候需要做一个设置。

如果是通过java.sql.Statement执行sql,需要调用下面这个方法:

int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException

注意上面这个方法的第二个参数需要设置为java.sql.Statement.RETURN_GENERATED_KEYS,表示需要返回自增列的值。

不过多数情况下,我们会使用java.sql.PreparedStatement对象来执行sql,如果想获取自增值,创建这个对象需要设置第2个参数的值,如下:

PreparedStatement preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);

然后我们就可以通过getGeneratedKeys返回的ResultSet对象获取自动增长的值了,如下:

ResultSet generatedKeys = preparedStatement.getGeneratedKeys();
if (generatedKeys!=null && generatedKeys.next()) {
    log.info("自增值为:{}", generatedKeys.getInt(1));
}

方式2:插入之后查询获取

用法

当然除了jdbc想到了我们这个需求,mysql数据库也想到了这个需求也有对应的语句来帮助我们在插入数据后获取最新插入记录的id值,如下所示

SELECT LAST_INSERT_ID()

所以我们可以在插入之后,立即使用当前连接发送上面这条sql去获取自增列的值就可以。这种方法相对来说十分的简单和方便,但是也存在着一些问题,就是在高并发多线程的情况 ,可能会出现严重的问题,所以一般来说不建议使用。

方式3:插入之前获取

最后一种方法就是在插入之前获取。

oracle不知道大家有没有玩过,oracle中没有mysql中自动增长列,但是oracle有个功能可以实现自动增长,这个功能就是序列,序列就相当于一个自增器一样,有个初始值,每次递增的步长,当然这个序列提供了一些功能给我们使用,可以获取序列的当前值、下一个值,使用方式如下:

  • 先定义一个序列
  • 获取下一个值:SELECT 序列名.NEXTVAL FROM dual;

mybatis获取主键的3种方式

既然jdbc有三种方法,那么mybatis也有相应的几种方法。

方式1:内部使用jdbc内置的方式

用法

mybatis这个方式内部采用的是上面说的jdbc内置的方式。

我们需要在Mapper xml中进行配置,如:

<insert id="insertUser1" parameterType="zhonghu.mybatis.chat01.UserModel" useGeneratedKeys="true" keyProperty="id">
    <![CDATA[
    INSERT INTO user (name,age,salary) VALUES (#{name},#{age},#{salary})
     ]]>
</insert>

有2个关键参数必须要设置:

  • useGeneratedKeys:设置为true
  • keyProperty:参数对象中的属性名称,最后插入成功之后,mybatis会通过反射将自增值设置给keyProperty指定的这个属性

方式2:插入后查询获取主键

用法

这个方式和上面介绍的jdbc的第二种方式一样,插入之后通过查询获取主键的值然后填充给指定的属性,mapper xml配置如下:

<insert id="insertUser2" parameterType="zhonghu.mybatis.chat01.UserModel">
    <selectKey keyProperty="id" order="AFTER" resultType="long">
    <![CDATA[
    SELECT LAST_INSERT_ID()
     ]]>
    </selectKey>
    <![CDATA[
    INSERT INTO user (name,age,salary) VALUES (#{name},#{age},#{salary})
     ]]>
</insert>

关键代码是selectKey元素包含的部分,这个元素内部可以包含一个sql,这个sql可以在插入之前或者插入之后运行(之前还是之后通过order属性配置),然后会将sql运行的结果设置给keyProperty指定的属性,selectKey元素有3个属性需要指定:

  • keyProperty:参数对象中的属性名称,最后插入成功之后,mybatis会通过反射将自增值设置给keyProperty指定的这个属性
  • order:指定selectKey元素中的sql是在插入之前运行还是插入之后运行,可选值(BEFORE|AFTER),这种方式中我们选择AFTER
  • resultType:keyProperty指定的属性对应的类型,如上面的id对应的类型是java.lang.Long,我们直接写的是别名long

方式3:插入前查询获取主键

用法

这个方式和上面介绍的jdbc的第3种方式一样,会在插入之前先通过一个查询获取主键的值然后填充给指定的属性,然后在执行插入,mapper xml配置如下:

<insert id="insertUser3" parameterType="zhonghu.mybatis.chat01.UserModel">
    <selectKey keyProperty="id" order="BEFORE" resultType="long">
    <![CDATA[ 获取主键的select语句 ]]>
    </selectKey>
    <![CDATA[
    INSERT INTO user (name,age,salary) VALUES (#{name},#{age},#{salary})
     ]]>
</insert>

关键代码是selectKey元素包含的部分,这个元素内部可以包含一个sql,这个sql可以在插入之前或者插入之后运行(之前还是之后通过order属性配置),然后会将sql运行的结果设置给keyProperty指定的属性,selectKey元素有3个属性需要指定:

  • keyProperty:参数对象中的属性名称,最后插入成功之后,mybatis会通过反射将自增值设置给keyProperty指定的这个属性
  • order:指定selectKey元素中的sql是在插入之前运行还是插入之后运行,可选值(BEFORE|AFTER),这种方式中我们选择BEFORE
  • resultType:keyProperty指定的属性对应的类型,如上面的id对应的类型是java.lang.Long,我们直接写的是别名long

总结

本篇文章着重介绍了mybatis中一些增删改查的高级使用方法,尤其是获取主键的方法,在此进行了jdbc和mybatis对比介绍了三种方法。

最后

  • 如果觉得看完有收获,希望能关注一下,顺便给我点个赞,这将会是我更新的最大动力,感谢各位的支持
  • 欢迎各位关注我的公众号【java冢狐】,专注于java和计算机基础知识,保证让你看完有所收获,不信你打我
  • 求一键三连:点赞、转发、在看。
  • 如果看完有不同的意见或者建议,欢迎多多评论一起交流。感谢各位的支持以及厚爱。

——我是冢狐,和你一样热爱编程。

欢迎关注公众号“ Java冢狐”,获取最新消息

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
(八)MyBatis从入门到入土——自动映射的使用
这是mybatis系列第8篇。没看前文的建议先去【Java冢狐】公众号中查看前文,方便理解和掌握。在上一篇中我们介绍了一些mybatis使用查询的一些方式,特别是一对一查询和一对多查询进行了重点介绍。没看的推荐去公众号进行查看。今天我们介绍一下我们一直在使用的但是没有来得及做过多介绍的自动映射。什么是自动映射?介绍自动映射之前先
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这