insert語句返回主鍵和selectKey標簽
往數據庫中插入一條記錄后,有時候我們需要這條記錄的主鍵,用于后續的操作。
如果在插入后再去查一次數據庫,顯然不夠優雅和效率,MyBatis中已經有了insert后返回主鍵的功能,下面就主要講幾種不同情況的具體做法。
1.主鍵自增的情況
對于MySQL和Sql Server這種支持主鍵自增的數據庫,可以設置useGeneratedKeys="true"和keyProperty。例如現在有一個表 tbl_employee,表有id,name,age,create_time四個字段,MyBatis映射文件中可以寫成如下:
1
2
3
4
5
|
< insert id= "insertRecord" parameterType= "com.lzumetal.mybatis.entity.Employee" useGeneratedKeys= "true" keyProperty= "id" > INSERT INTO tbl_employee( name , age, create_time) VALUES (#{ name }, #{age}, #{createTime}) </ insert > |
- useGeneratedKeys="true":使用自動生成的主鍵
- keyProperty:指定主鍵是(javaBean的)哪個屬性。
useGeneratedKeys:
(insert and update only) This tells MyBatis to use the JDBC getGeneratedKeys method to retrieve keys generated internally by the database (e.g.auto increment fields in RDBMS like MySQL or SQL Server). Default: falsekeyProperty:
(insert and update only) Identifies a property into which MyBatis will set the key value returned by getGeneratedKeys , or by a selectKey child element of the insert statement. Default: unset .
Can be a comma separated list of property names if multiple generated columns are expected.
2.Oracle中用Sequence獲取主鍵
對于Oracle數據庫,當要用到自增字段時,需要用到Sequence,假設我們現在已經創建了一個名字為SEQ_ADMIN的 Sequence,在MyBatis中的映射文件中可以結合selectKey標簽使用。
1
2
3
4
5
6
7
|
< insert id= "insert" parameterType= "com.lzumetal.mybatis.entity.Employee" > <selectKey keyProperty= "id" resultType= "long" order = "BEFORE" > SELECT SEQ_ADMIN.NEXTVAL FROM DUAL </selectKey> INSERT INTO tbl_employee(id, name , age, create_time) VALUES (#{id}, #{ name }, #{age}, #{createTime}) </ insert > |
order="BEFORE"表示SELECT SEQ_ADMIN.NEXTVAL FROM DUAL在 INSERT 語句執行之前先對id進行賦值。相反的,order還可以設置成AFTER,表示在INSERT語句執行完后,再查詢一次slectKey標簽中的語句,并賦值到Javabean的keyProperty的那個屬性上。
源碼分析
從源碼上來分析,在BaseStatementHandler里面有生成generateKeys,主要是執行:
1
2
3
4
5
6
|
protected void generateKeys(Object parameter) { KeyGenerator keyGenerator = mappedStatement.getKeyGenerator(); ErrorContext.instance().store(); keyGenerator.processBefore(executor, mappedStatement, null , parameter); ErrorContext.instance().recall(); } |
processBefore,表示執行前處理,對應mapper里面的selectKey中的order="BEFORE"屬性,先執行查詢key,并設置到參數對象中。
在各個聲明處理器中,update有代碼:
1
2
|
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator(); keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject); |
processAfter,表示執行后處理,對應mapper里面的selectKey中的order="AFTER"屬性,表示執行后,再查一遍key,設置到參數對象中。
MyBatis insert語句key的生成和返回
1.使用數據庫自帶的生成器
1
2
3
|
< insert id= "insertOne" keyProperty= "userId" useGeneratedKeys= "true" > insert into user (user_name) values (#{userName}) </ insert > |
mybatis會獲取數據庫自動生成的列,并把值賦值給傳入參數的userId屬性。
2.使用selectKey
1
2
3
4
5
6
|
< insert id= "insertOne" > insert into user (user_name) values (#{userName}) <selectKey order = "AFTER" keyProperty= "userId" > SELECT LAST_INSERT_ID() </selectKey> </ insert > |
插入語句執行后selectKey語句,并把返回值塞進傳入參數的userId屬性。
1
2
3
4
5
6
|
< insert id= "insertOne" > insert into user (user_name) values (#{userName}) <selectKey order = "BEFORE" keyProperty= "userId" > SELECT LAST_INSERT_ID() </selectKey> </ insert > |
先執行selectKey,并把返回值賦值給傳入參數的userId屬性,然后執行insert語句。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。
原文鏈接:https://segmentfault.com/a/1190000014699207