详解mysql插入数据后返回自增ID的七种方法

引言

mysql 和 oracle 插入的时候有一个很大的区别是:

  • oracle 支持序列做 id;
  • mysql 本身有一个列可以做自增长字段。

mysql 在插入一条数据后,如何能获得到这个自增 id 的值呢?

一:使用 last_insert_id()

SELECT LAST_INSERT_ID();

1. 每次 mysql 的 query 操作在 mysql 服务器上可以理解为一次“原子”操作, 写操作常常需要锁表, 这里的锁表是 mysql 应用服务器锁表不是我们的应用程序锁表。

2. 因为 LAST_INSERT_ID 是基于 Connection 的,只要每个线程都使用独立的 Connection 对象,LAST_INSERT_ID 函数 将返回该 Connection 对 AUTO_INCREMENT列 最新的 insert or update* 作生成的第一个 record 的ID。这个值不能被其它客户端(Connection)影响,保证了你能够找回自己的 ID 而不用担心其它客户端的活动,而且不需要加锁。使用单INSERT 语句插入多条记录,  LAST_INSERT_ID 返回一个列表。
   3. LAST_INSERT_ID 是与 table 无关的,如果向表 a 插入数据后,再向表 b 插入数据,LAST_INSERT_ID 会改变。

二:使用 max(id)

如果不是频繁的插入我们也可以使用这种方法来获取返回的id值

select max(id) from user;

这个方法的缺点是不适合高并发。如果同时插入的时候返回的值可能不准确。

三:创建一个存储过程

在存储过程中调用先插入再获取最大值的操作。

DELIMITER $$
DROP PROCEDURE IF EXISTS `test` $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `test`(in name varchar(100),out oid int)
BEGIN
 insert into user(loginname) values(name);
 select max(id) from user into oid;
 select oid;
END $$
DELIMITER ;
call test('gg',@id);

四:使用 @@identity

select @@IDENTITY

@@identity 是表示的是最近一次向具有 identity 属性(即自增列)的表插入数据时对应的自增列的值,是系统定 义的全局变量。一般系统定义的全局变量都是以@@开头,用户自定义变量以@开头。比如有个表 A,它的自增列是 id,当向 A 表插入一行数据后,如果插入数据 后自增列的值自动增加至 101,则通过select @@identity得到的值就是 101。使用@@identity的前提是在进行 insert 操作后,执行 select @@identity 的时候连接没有关闭,否则得到的将是 NULL 值。

五:是使用 getGeneratedKeys()

Connection conn = ;
Serializable ret = null;
PreparedStatement state = .;
ResultSet rs=null;
try {
  state.executeUpdate();
  rs = state.getGeneratedKeys();
  if (rs.next()) {
    ret = (Serializable) rs.getObject(1);
  }
} catch (SQLException e) {
}
return ret;

总结:在 mysql 中做完插入之后获取 id 在高并发的时候是很容易出错的。另外 last_insert_id 虽然是基于 session 的但是不知道为什么没有测试成功。

六:selectkey:

其实在 ibtias 框架里使用 selectkey 这个节点,并设置 insert 返回值的类型为 integer,就可以返回这个 id 值。

SelectKey 在Mybatis中是为了解决 Insert 数据时不支持主键自动生成的问题,他可以很随意的设置生成主键的方式。

不管 SelectKey 有多好,尽量不要遇到这种情况吧,毕竟很麻烦。

SelectKey 需要注意 order 属性:

  • Mysql 一类支持自动增长类型的数据库中,order 需要设置为 after 才会取到正确的值。
  • Oracle 这样取序列的情况,需要设置为 before,否则会报错。

xml 的例子:

<insert id="insert" parameterType="map">
  insert into table1 (name) values (#{name})
  <selectKey resultType="java.lang.Integer" keyProperty="id">
   SELECT LAST_INSERT_ID() AS id
  </selectKey>
</insert>

上面 xml 的传入参数是 map,selectKey 会将结果放到入参数 map 中。用 POJO 的情况一样,但是有一点需要注意的是,keyProperty 对应的字段在 POJO 中必须有相应的 setter 方法,setter 的参数类型还要一致,否则会报错。

注解的形式:

@Insert("insert into table2 (name) values(#{name})")
@SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class)
int insertTable2(Name name);

方法七:使用<insert 中的useGeneratedKeys 和 keyProperty 两个属性

1.在Mybatis Mapper文件中添加属性 “useGeneratedKeys”和“keyProperty”,其中 keyProperty 是 Java 对象的属性名,而不是表格的字段名。

<insert id="insert" parameterType="Spares"
    useGeneratedKeys="true" keyProperty="id">
    insert into system(name) values(#{name})
</insert>

2.Mybatis 执行完插入语句后,自动将自增长值赋值给对象 systemBean 的属性id。因此,可通过 systemBean 对应的 getter 方法获取!

int count = systemService.insert(systemBean);
int id = systemBean.getId(); //获取到的即为新插入记录的ID

【注意事项】

1.Mybatis Mapper 文件中,“useGeneratedKeys” 和 “keyProperty” 必须添加,而且 keyProperty 一定得和 java 对象的属性名称一直,而不是表格的字段名。

2. java Dao中的 Insert 方法,传递的参数必须为 java 对象,也就是 Bean,而不能是某个参数。

到此这篇关于详解mysql插入数据后返回自增ID的七种方法的文章就介绍到这了,更多相关mysql插入返回自增ID内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Mysql join联表及id自增实例解析

    join的写法 如果用left join 左边的表一定是驱动表吗?两个表的join包含多个条件的等值匹配,都要写道on还是只把一个写到on,其余写道where部分? create table a(f1 int, f2 int, index(f1))engine=innodb; create table b(f1 int, f2 int)engine=innodb; insert into a values(1,1),(2,2),(3,3),(4,4),(5,5),(6,6); insert in

  • 关于mysql自增id,你需要知道的

    导读:在使用MySQL建表时,我们通常会创建一个自增字段(AUTO_INCREMENT),并以此字段作为主键.本篇文章将以问答的形式讲述关于自增id的一切. 注: 本文所讲的都是基于Innodb存储引擎. 1.MySQL为什么建议将自增列id设为主键? 如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择主键作为聚集索引.如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作为主键索引.如果也没有这样的唯一索引,则InnoDB会选择内置6字节长的ROWID

  • MySQL分表自增ID问题的解决方法

    当我们对MySQL进行分表操作后,将不能依赖MySQL的自动增量来产生唯一ID了,因为数据已经分散到多个表中.  应尽量避免使用自增IP来做为主键,为数据库分表操作带来极大的不便.  在postgreSQL.oracle.db2数据库中有一个特殊的特性---sequence. 任何时候数据库可以根据当前表中的记录数大小和步长来获取到该表下一条记录数.然而,MySQL是没有这种序列对象的.  可以通过下面的方法来实现sequence特性产生唯一ID:  1. 通过MySQL表生成ID  对于插入也

  • mysql自增id超大问题的排查与解决

    引言 小A正在balabala写代码呢,DBA小B突然发来了一条消息,"快看看你的用户特定信息表T,里面的主键,也就是自增id,都到16亿了,这才多久,在这样下去过不了多久主键就要超出范围了,插入就会失败,balabala......" 我记得没有这么多,最多1k多万,count了下,果然是1100万.原来运维是通过auto_increment那个值看的,就是说,表中有大量的删除插入操作,但是我大部分情况都是更新的,怎么会这样? 下面话不多说了,来一起看看详细的介绍吧 问题排查 这张表

  • MySQL的自增ID(主键) 用完了的解决方法

    在 MySQL 中用很多类型的自增 ID,每个自增 ID 都设置了初始值.一般情况下初始值都是从 0 开始,然后按照一定的步长增加(一般是自增 1).一般情况下,我们都是用int(11)来作为数据表的自增 ID,在 MySQL 中只要定义了这个数的字节长度,那么就会有上限. MySQL的自增ID(主键) 用完了,怎么办? 如果用 int unsigned (int,4个字节 ), 我们可以算下最大当前声明的自增ID最大是多少,由于这里定义的是 int unsigned,所以最大可以达到2的32幂

  • 关于MySQL自增ID的一些小问题总结

    下面这几个小问题都是基于 InnoDB 存储引擎的. 1. ID最大的记录删除后,新插入的记录ID是什么 例如当前表中有ID为1,2,3三条记录,把3删除,新插入记录的ID从哪儿开始? 答案: 从4开始. 实验 创建表 tb0,ID自增: create table tb0(id int unsigned auto_increment primary key); 插入3条记录: insert into tb0 values(null); 删除ID为3的记录: delete from tb0 whe

  • MySQL自增ID耗尽实例讲解

    显示定义ID 表定义的自增值ID达到上限后,在申请下一个ID时,得到的值保持不变 -- (2^32-1) = 4,294,967,295 -- 建议使用 BIGINT UNSIGNED CREATE TABLE t (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY) AUTO_INCREMENT=4294967295; INSERT INTO t VALUES (null); -- AUTO_INCREMENT没有改变 mysql> SHOW CREATE

  • 详解mysql插入数据后返回自增ID的七种方法

    引言 mysql 和 oracle 插入的时候有一个很大的区别是: oracle 支持序列做 id: mysql 本身有一个列可以做自增长字段. mysql 在插入一条数据后,如何能获得到这个自增 id 的值呢? 一:使用 last_insert_id() SELECT LAST_INSERT_ID(); 1. 每次 mysql 的 query 操作在 mysql 服务器上可以理解为一次"原子"操作, 写操作常常需要锁表, 这里的锁表是 mysql 应用服务器锁表不是我们的应用程序锁表

  • 详解mybatis插入数据后返回自增主键ID的问题

    1.场景介绍: ​开发过程中我们经常性的会用到许多的中间表,用于数据之间的对应和关联.这个时候我们关联最多的就是ID,我们在一张表中插入数据后级联增加到关联表中.我们熟知的mybatis在插入数据后返回的是插入成功的条数,那么这个时候我们想要得到相应的这条新增数据的ID,该怎么办呢? 2.插入数据返回自增主键ID方法(一) 在映射器中配置获取记录主键值xml映射: 在xml中定义useGeneratedKeys为true,返回主键id的值,keyProperty和keyColumn分别代表数据库

  • 如何用注解的方式实现Mybatis插入数据时返回自增的主键Id

    目录 用注解实现Mybatis插入数据返回自增的主键Id 设计数据库表 设计Java bean对象 添加mapper接口 Mybatis注解增(返回自增id) 删查改以及(一对一,一对多,多对多) 数据库表 目录结构 导入坐标(包) 配置文件 实体类 mapper接口编写 测试 用注解实现Mybatis插入数据返回自增的主键Id 我们在数据库表设计的时候,一般都会在表中设计一个自增的id作为表的主键.这个id也会关联到其它表的外键. 这就要求往表中插入数据时能返回表的自增id,用这个ID去给关联

  • 详解MySQL的数据行和行溢出机制

    一.行 有哪些格式? 你可以像下面这样看一下你的MySQL行格式设置. 其实MySQL的数据行有两种格式,一种就是图中的 Compact格式,还有一种是Redundant格式. Compact是一种紧凑的行格式,设计的初衷就是为了让一个数据页中可以存放更多的数据行. 你品一品,让一个数据页中可以存放更多的数据行是一个多么激动人心的事,MySQL以数据页为单位从磁盘中读数据,如果能做到让一个数据页中有更多的行,那岂不是使用的空间变少了,且整体的效率直线飙升? 官网介绍:Compact能比Redun

  • 一文详解MySQL中数据表的外连接

    目录 为什么要使用外连接 外连接简介 左连接与右连接 外连接练习① 外连接练习② 该章节的内容为多表连接查询的外连接,因为 MySQL 是关系型数据库,数据是拆分重组在多个数据表里面的.所以我们势必要从多个数据表中提取数据,通过 SQL 语句的内连接与外连接就能够实现多表查询了.这部分内容是需要我们重点学习的,学习的过程中会穿插多种的案例来强化对表连接的语法的运用. 为什么要使用外连接 在解释为什么使用 “外连接” 之前,先来看一个记录.(如下:) 针对表中的张三没有所属的部门编号,我们暂且将他

  • 详解 Mysql查询结果顺序按 in() 中ID 的顺序排列

    详解 Mysql查询结果顺序按 in() 中ID 的顺序排列 实例代码: <select id="queryGBStyleByIDs" resultMap="styleMap"> select style_num_id ,style_id,style_title,style_pic FROM gb_style where online = 1 AND is_hide = 0 and style_num_id in <foreach collecti

  • 详解MySQL插入和查询数据的相关命令及语句使用

    插入数据 MySQL 表中使用 INSERT INTO SQL语句来插入数据. 你可以通过 mysql> 命令提示窗口中向数据表中插入数据,或者通过PHP脚本来插入数据. 语法 以下为向MySQL数据表插入数据通用的 INSERT INTO SQL语法: INSERT INTO table_name ( field1, field2,...fieldN ) VALUES ( value1, value2,...valueN ); 如果数据是字符型,必须使用单引号或者双引号,如:"value

  • Mybatis实现插入数据后返回主键过程解析

    添加记录后获取主键ID,这是一个很常见的需求,特别是在一次前端调用中需要插入多个表的场景. 除了添加单条记录时获取主键值,有时候可能需要获取批量添加记录时各记录的主键值,MyBatis从3.3.1版本开始支持批量添加记录并返回各记录主键字段值. 一.获取新添加记录主键字段值 注意: 在MyBatis中添加操作返回的是记录数并非记录主键id. 如果需要获取新添加记录的主键值,需要在执行添加操作之后,直接读取Java对象的主键属性. Integer rows = sqlSession.getMapp

  • 详解Mysql导出数据的几种方式

    MySQL导出数据的目的有很多种,如数据库备份.表结构导出.表数据导出.分析数据采取等. Part1 select into outfile 先说最短小精悍的select into outfile, 这是小型数据库分析数据最常用的采集数据方式,具体语法如下: [select 语句] into outfile [导出文件名] [导出参数] [select语句]是经典的查询SQL,可以指定列.可以有where条件.group.order.limit等. [导出文件名]是目标文件的完整路径.由于mys

  • 详解使用python的logging模块在stdout输出的两种方法

    详解使用python的logging模块在stdout输出 前言: 使用python的logging模块时,除了想将日志记录在文件中外,还希望在前台执行python脚本时,可以将日志直接输出到标准输出std.out中. 实现 logging模块可以有两种方法实现该功能: 方案一:basicconfig import sys import logging logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) 方案二:handler

随机推荐