java獲取新insert數(shù)據(jù)自增id的實(shí)現(xiàn)方法
在MySQL中,使用auto_increment類型的id字段作為表的主鍵,并用它作為其他表的外鍵,形成“主從表結(jié)構(gòu)”,這是數(shù)據(jù)庫設(shè)計(jì)中常見的用法。但是在具體生成id的時(shí)候,我們的操作順序一般是:先在主表中插入記錄,然后獲得自動(dòng)生成的id,以它為基礎(chǔ)插入從表的記錄。
這里面有個(gè)困難,就是插入主表記錄后,如何獲得它對(duì)應(yīng)的id。通常的做法,是通過“select max(id) from tablename”的做法,但是顯然這種做法需要考慮并發(fā)的情況,需要在事務(wù)中對(duì)主表加以“X鎖“,待獲得max(id)的值以后,再解鎖。這種做法需要的步驟比較多,有些麻煩,而且并發(fā)性也不好。有沒有更簡(jiǎn)單的做法呢?
答案之一是通過select LAST_INSERT_ID()這個(gè)操作。乍一看,它和select max(id)很象,但實(shí)際上它是線程安全的。也就是說它是具體于數(shù)據(jù)庫連接的。下面通過實(shí)驗(yàn)說明:
1、在連接1中向A表插入一條記錄,A表包含一個(gè)auto_increment類型的字段。
2、在連接2中向A表再插入一條記錄。
3、結(jié)果:在連接1中執(zhí)行select LAST_INSERT_ID()得到的結(jié)果和連接2中執(zhí)行select LAST_INSERT_ID()的結(jié)果是不同的;而在兩個(gè)連接中執(zhí)行select max(id)的結(jié)果是相同的。
其實(shí)在MSSQL中SCOPE_IDENTITY()和IDENT_CURRENT()的區(qū)別和這里是類似的。使用SCOPE_IDENTITY()可以獲得插入某個(gè)IDENTITY字段的當(dāng)前會(huì)話的值,而使用IDENT_CURRENT()會(huì)獲得在某個(gè)IDENTITY字段上插入的最大值,而不區(qū)分不同的會(huì)話。
注:使用select last_insert_id()時(shí)要注意,當(dāng)一次插入多條記錄時(shí),只是獲得第一次插入的id值,務(wù)必注意!
當(dāng)然,我們還可以使用另一種更加便捷的方法:在JDBC追加記錄后,使用API獲得新追加記錄的主鍵值。
這個(gè)實(shí)現(xiàn)使用了Statement的getGeneratedKeys方法,
當(dāng)Statement追加了一條記錄后,可以直接調(diào)用getGeneratedKeys方法獲得新追加記錄的key。
測(cè)試程序如下:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class GetGenerateKey {
public static void main(String[] args) throws Exception {
create();
}
public static void create()throws Exception {
System.setProperty("jdbc.drivers", "com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc", "root", "");
Statement st = conn.createStatement();
String sql = "insert into user (name, birthday, money) values ('beck', '1949-10-01', 60)";
st.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
ResultSet rs = st.getGeneratedKeys();
if (rs.next()) {
int id = rs.getInt(1);
System.out.println ("生成記錄的key為 :" + id);
}
st.close();
conn.close();
}
}
程序運(yùn)行結(jié)果:
生成記錄的key為 :9
數(shù)據(jù)庫的記錄為:
1 +----+----------+------------+-------+ 2 | id | name | birthday | money | 3 +----+----------+------------+-------+ 4 | 9 | beck | 1949-10-01 | 60 | 5 +----+----------+------------+-------+
總結(jié):這個(gè)API方法提供的好處就是不用重新再執(zhí)行一次查詢獲得新記錄的key值。減少了工作量和服務(wù)器的負(fù)擔(dān)。
注意點(diǎn),在執(zhí)行executeUpdate方法的時(shí)候,要指定返回生成key的選項(xiàng)。
===========================================================
2種方法的java 代碼
Java代碼1
// 用這種方法能得到插入自增的id 很好用
PreparedStatement pstmt = conn.prepareStatement(sql.toString(),PreparedStatement.RETURN_GENERATED_KEYS);
for (int i = 0; i < pars.length; i++) {
pstmt.setObject(i+1, pars[i]);
}
pstmt.executeUpdate();
long autoIncKeyFromApi = -1;
ResultSet rs = pstmt.getGeneratedKeys();
if (rs.next()) {
autoIncKeyFromApi = rs.getInt(1);
}
return autoIncKeyFromApi;
Java代碼2
qRunner.update(conn,sql.toString(),pars); Long zsysqID = (Long) qRunner.query(conn, "SELECT LAST_INSERT_ID()", new ScalarHandler(1));
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
javaweb用戶注銷后點(diǎn)擊瀏覽器返回刷新頁面重復(fù)登錄問題的解決方法
這篇文章主要為大家詳細(xì)介紹了javaweb用戶注銷后點(diǎn)擊瀏覽器返回刷新頁面重復(fù)登錄問題的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09
SpringCloud Ribbon與OpenFeign詳解如何實(shí)現(xiàn)服務(wù)調(diào)用
這篇文章主要介紹了SpringCloud Ribbon與OpenFeign實(shí)現(xiàn)服務(wù)調(diào)用的過程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-09-09
ssm框架controller層返回json格式數(shù)據(jù)到頁面的實(shí)現(xiàn)
這篇文章主要介紹了ssm框架controller層返回json格式數(shù)據(jù)到頁面的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
java原生序列化和Kryo序列化性能實(shí)例對(duì)比分析
這篇文章主要介紹了java原生序列化和Kryo序列化性能實(shí)例對(duì)比分析,涉及Java和kryo序列化和反序列化相關(guān)實(shí)例,小編覺得很不錯(cuò),這里分享給大家,希望給大家一個(gè)參考。2017-10-10
Spring中使用atomikos+druid實(shí)現(xiàn)經(jīng)典分布式事務(wù)的方法
這篇文章主要介紹了Spring中使用atomikos+druid實(shí)現(xiàn)經(jīng)典分布式事務(wù)的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-06-06

