【轉載】詳解mysql插入資料後返回自增ID的七種方法_java
引言
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,而不能是某個引數。
原文:https://blog.csdn.net/qq_30715329/article/details/80868411