转自:http://blog.csdn.net/ultrani/article/details/9351573

作者已经写的非常好了,我不废话了,直接转载收藏:

通常我们在应用中对mysql执行了insert操作后,需要获取插入记录的自增主键。本文将介绍java环境下的4种方法获取insert后的记录主键auto_increment的值:

  1. 通过JDBC2.0提供的insertRow()方式
  2. 通过JDBC3.0提供的getGeneratedKeys()方式
  3. 通过SQL select LAST_INSERT_ID()函数
  4. 通过SQL @@IDENTITY 变量

1. 通过JDBC2.0提供的insertRow()方式

自jdbc2.0以来,可以通过下面的方式执行。

Statement stmt = null;
ResultSet rs = null;
try {
stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, // 创建Statement
java.sql.ResultSet.CONCUR_UPDATABLE);
stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial");
stmt.executeUpdate( // 创建demo表
"CREATE TABLE autoIncTutorial ("
+ "priKey INT NOT NULL AUTO_INCREMENT, "
+ "dataField VARCHAR(64), PRIMARY KEY (priKey))");
rs = stmt.executeQuery("SELECT priKey, dataField " // 检索数据
+ "FROM autoIncTutorial");
rs.moveToInsertRow(); // 移动游标到待插入行(未创建的伪记录)
rs.updateString("dataField", "AUTO INCREMENT here?"); // 修改内容
rs.insertRow(); // 插入记录
rs.last(); // 移动游标到最后一行
int autoIncKeyFromRS = rs.getInt("priKey"); // 获取刚插入记录的主键preKey
rs.close();
rs = null;
System.out.println("Key returned for inserted row: "
+ autoIncKeyFromRS);
} finally {
// rs,stmt的close()清理
}

优点:早期较为通用的做法

缺点:需要操作ResultSet的游标,代码冗长。

2. 通过JDBC3.0提供的getGeneratedKeys()方式

Statement stmt = null;
ResultSet rs = null;
try {
stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
java.sql.ResultSet.CONCUR_UPDATABLE);
// ...
// 省略若干行(如上例般创建demo表)
// ...
stmt.executeUpdate(
"INSERT INTO autoIncTutorial (dataField) "
+ "values ('Can I Get the Auto Increment Field?')",
Statement.RETURN_GENERATED_KEYS); // 向驱动指明需要自动获取generatedKeys!
int autoIncKeyFromApi = -;
rs = stmt.getGeneratedKeys(); // 获取自增主键!
if (rs.next()) {
autoIncKeyFromApi = rs.getInt();
} else {
// throw an exception from here
}
rs.close();
rs = null;
System.out.println("Key returned from getGeneratedKeys():"
+ autoIncKeyFromApi);
} finally { ... }

这种方式只需要2个步骤:

1. 在executeUpdate时激活自动获取key;
2.调用Statement的getGeneratedKeys()接口
优点:
1. 操作方便,代码简洁
2. jdbc3.0的标准
3. 效率高,因为没有额外访问数据库
 
这里补充下,
a.在jdbc3.0之前,每个jdbc driver的实现都有自己获取自增主键的接口。在mysql jdbc2.0的driver org.gjt.mm.mysql中,getGeneratedKeys()函数就实现在org.gjt.mm.mysql.jdbc2.Staement.getGeneratedKeys()中。这样直接引用的话,移植性会有很大影响。JDBC3.0通过标准的getGeneratedKeys很好的弥补了这点。
b.关于getGeneratedKeys(),官网还有更详细解释:OracleJdbcGuide

3. 通过SQL select
LAST_INSERT_ID()

Statement stmt = null;
ResultSet rs = null;
try {
stmt = conn.createStatement();
// ...
// 省略建表
// ...
stmt.executeUpdate(
"INSERT INTO autoIncTutorial (dataField) "
+ "values ('Can I Get the Auto Increment Field?')");
int autoIncKeyFromFunc = -;
rs = stmt.executeQuery("SELECT LAST_INSERT_ID()"); // 通过额外查询获取generatedKey
if (rs.next()) {
autoIncKeyFromFunc = rs.getInt();
} else {
// throw an exception from here
}
rs.close();
System.out.println("Key returned from " +
"'SELECT LAST_INSERT_ID()': " +
autoIncKeyFromFunc);
} finally {...}

这种方式没什么好说的,就是额外查询一次函数LAST_INSERT_ID().

优点:简单方便
缺点:相对JDBC3.0的getGeneratedKeys(),需要额外多一次数据库查询。
 
补充:
1. 这个函数,在mysql5.5手册的定义是:“returns a BIGINT (64-bit) value representing the first automatically generated value successfully inserted for an AUTO_INCREMENT column as a result of the most recently executed INSERT statement.”。文档点此
2. 这个函数,在connection维度上是“线程安全的”。就是说,每个mysql连接会有个独立保存LAST_INSERT_ID()的结果,并且只会被当前连接最近一次insert操作所更新。也就是2个连接同时执行insert语句时候,分别调用的LAST_INSERT_ID()不会相互覆盖。举个栗子:连接A插入表后LAST_INSERT_ID()返回100,连接B插入表后LAST_INSERT_ID()返回101,但是连接A重复执行LAST_INSERT_ID()的时候,始终返回100,而不是101。这个可以通过监控mysql连接数和执行结果来验证,这里不详述实验过程。
3. 在上面那点的基础上,如果在同一个连接的前提下同时执行insert,那可能2次操作的返回值会相互覆盖。因为LAST_INSERT_ID()的隔离程度是连接级别的。这点,getGeneratedKeys()是可以做的更好,因为getGeneratedKeys()是statement级别的。同个connection的多次statement,getGeneratedKeys()是不会被相互覆盖。

4. 通过SQL SELECT @@IDENTITY

这个方式和LAST_INSERT_ID()效果是一样的。官网文档如此表述:“This variable is a synonym for the last_insert_id variable. It exists for compatibility with other database systems. You can read its value with SELECT @@identity, and set it using SET identity.” 文档点此
 
重要补充:
无论是SELECT LAST_INSERT_ID()还是SELECT
@@IDENTITY,对于一条insert语句插入多条记录,永远只会返回第一条插入记录的generatedKey.如:
INSERT INTO t VALUES
-> (NULL, 'Mary'), (NULL, 'Jane'), (NULL, 'Lisa');

LAST_INSERT_ID(), @@IDENTITY都只会返回'Mary'所在的那条记录的generatedKey

小结

所以,最好还是通过JDBC3 提供的getGeneratedKeys()函数来获取insert记录的主键。不但简单,而且效率高。
 
在mybatis中,就有相关设置: 
<insert id="save" parameterType="MappedObject" useGeneratedKeys="true" keyProperty="id">
</insert>

可参考mybatis文档:sqlmap-xml

参考资料

MYSQL获取自增主键【4种方法】(转)的更多相关文章

  1. MYSQL获取自增ID的四种方法

    MYSQL获取自增ID的四种方法 1. select max(id) from tablename 2.SELECT LAST_INSERT_ID() 函数 LAST_INSERT_ID 是与tabl ...

  2. DBS-MySQL:MYSQL获取自增ID的四种方法

    ylbtech-DBS-MySQL:MYSQL获取自增ID的四种方法 1.返回顶部 1. 1. select max(id) from tablename 2.SELECT LAST_INSERT_I ...

  3. MYSQL获取自增主键【4种方法】

    通常我们在应用中对mysql执行了insert操作后,需要获取插入记录的自增主键.本文将介绍java环境下的4种方法获取insert后的记录主键auto_increment的值: 通过JDBC2.0提 ...

  4. mysql 获取自增主键

    MyBatis 3.2.6插入时候获取自增主键方法有二 以MySQL5.5为例: 方法1: <insert id="insert" parameterType="P ...

  5. 【JAVA - SSM】之MyBatis插入数据后获取自增主键

    很多时候,我们都需要在插入一条数据后回过头来获取到这条数据在数据表中的自增主键,便于后续操作.针对这个问题,有两种解决方案: (1)先插入,后查询.我们可以先插入一条数据,然后根据插入的数据的各个字段 ...

  6. mybatis框架(6)---mybatis插入数据后获取自增主键

    mybatis插入数据后获取自增主键 首先理解这就话的意思:就是在往数据库表中插入一条数据的同时,返回该条数据在数据库表中的自增主键值. 有什么用呢,举个例子: 你编辑一条新闻,同时需要给该新闻打上标 ...

  7. Mybatis学习笔记4 - 获取自增主键的值

    获取自增主键的值:mysql支持自增主键,自增主键值的获取,mybatis也是利用statement.getGenreatedKeys():useGeneratedKeys="true&qu ...

  8. 深入分析Mybatis 使用useGeneratedKeys获取自增主键

    摘要 我们经常使用useGenerateKeys来返回自增主键,避免多一次查询.也会经常使用on duplicate key update,来进行insertOrUpdate,来避免先query 在i ...

  9. 【JavaEE】之MyBatis插入数据后获取自增主键

    很多时候,我们都需要在插入一条数据后回过头来获取到这条数据在数据表中的自增主键,便于后续操作.针对这个问题,有两种解决方案: 先插入,后查询.我们可以先插入一条数据,然后根据插入的数据的各个字段值,再 ...

随机推荐

  1. html5一些容易忽略的细节

    最近由于经常写前端,所以系统性的看了一下html5页面的基础信息,虽然以前写了很久的html代码,但是其中的一些细节还是容易被忽略,所以这里一起整理一下. 在html5中,空元素结尾处的空格和斜杠是可 ...

  2. Java变量和运算符

    1.变量 变量概述 什么是变量?变量是一个内存中的小盒子(小容器),容器是什么?生活中也有很多容器,例如水杯是容器,用来装载水:你家里的大衣柜是容器,用来装载衣裤:饭盒是容器,用来装载饭菜.那么变量是 ...

  3. Linux下C语言多文件的编译以及makefile的应用

    1.关于编译和链接 一般来说,无论是C.C++,首先要把源文件编译成中间代码文件,在Windows下也就是.obj文件,UNIX下是.o文件,即Object File,这个动作叫做编译(compile ...

  4. UESTC 2015dp专题 F 邱老师看电影 概率dp

    邱老师看电影 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/65 Descr ...

  5. HAproxy + keepalived 实现双机热备

    一.HAProxy简介: HAProxy提供高可用性.负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费.快速并且可靠的一种解决方案.HAProxy特别适用于那些负载特大的web站点, ...

  6. 汇编语言学习笔记(十二)-浮点指令----ACM

    http://blog.csdn.net/q_l_s/article/details/54909328

  7. MYSQL GDB SHELL

    http://blog.163.com/xychenbaihu@yeah/blog/static/132229655201141165216974/

  8. std::string compare

    #include <iostream> #define NULL 0 #define MAX_LIMIT 5 //#define MAX_LENGTH 2 bool ComparePC2S ...

  9. zookeeper疑难杂症

    1.zookeeper是怎么写数据的?因为是master写再同步广播到follow节点,如果master写完,following在写的过程中出现失败怎么办? :zookeeper支持原子的写入操作,要 ...

  10. js数组的使用

    1.创建: var arr=Array(); 2.遍历: for(var arg in arr){ alert(arr[arg]); } 3.追加 arr1.concat(arr2) 4.元素删除 d ...