insert語(yǔ)句返回主鍵和selectKey標(biāo)簽
往數(shù)據(jù)庫(kù)中插入一條記錄后,有時(shí)候我們需要這條記錄的主鍵,用于后續(xù)的操作。
如果在插入后再去查一次數(shù)據(jù)庫(kù),顯然不夠優(yōu)雅和效率,MyBatis中已經(jīng)有了insert后返回主鍵的功能,下面就主要講幾種不同情況的具體做法。
1.主鍵自增的情況
對(duì)于MySQL和Sql Server這種支持主鍵自增的數(shù)據(jù)庫(kù),可以設(shè)置useGeneratedKeys="true"和keyProperty。例如現(xiàn)在有一個(gè)表 tbl_employee,表有id,name,age,create_time四個(gè)字段,MyBatis映射文件中可以寫(xiě)成如下:
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":使用自動(dòng)生成的主鍵
- keyProperty:指定主鍵是(javaBean的)哪個(gè)屬性。
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獲取主鍵
對(duì)于Oracle數(shù)據(jù)庫(kù),當(dāng)要用到自增字段時(shí),需要用到Sequence,假設(shè)我們現(xiàn)在已經(jīng)創(chuàng)建了一個(gè)名字為SEQ_ADMIN的 Sequence,在MyBatis中的映射文件中可以結(jié)合selectKey標(biāo)簽使用。
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 語(yǔ)句執(zhí)行之前先對(duì)id進(jìn)行賦值。相反的,order還可以設(shè)置成AFTER,表示在INSERT語(yǔ)句執(zhí)行完后,再查詢一次slectKey標(biāo)簽中的語(yǔ)句,并賦值到Javabean的keyProperty的那個(gè)屬性上。
源碼分析
從源碼上來(lái)分析,在BaseStatementHandler里面有生成generateKeys,主要是執(zhí)行:
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,表示執(zhí)行前處理,對(duì)應(yīng)mapper里面的selectKey中的order="BEFORE"屬性,先執(zhí)行查詢key,并設(shè)置到參數(shù)對(duì)象中。
在各個(gè)聲明處理器中,update有代碼:
1
2
|
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator(); keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject); |
processAfter,表示執(zhí)行后處理,對(duì)應(yīng)mapper里面的selectKey中的order="AFTER"屬性,表示執(zhí)行后,再查一遍key,設(shè)置到參數(shù)對(duì)象中。
MyBatis insert語(yǔ)句key的生成和返回
1.使用數(shù)據(jù)庫(kù)自帶的生成器
1
2
3
|
< insert id= "insertOne" keyProperty= "userId" useGeneratedKeys= "true" > insert into user (user_name) values (#{userName}) </ insert > |
mybatis會(huì)獲取數(shù)據(jù)庫(kù)自動(dòng)生成的列,并把值賦值給傳入?yún)?shù)的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 > |
插入語(yǔ)句執(zhí)行后selectKey語(yǔ)句,并把返回值塞進(jìn)傳入?yún)?shù)的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 > |
先執(zhí)行selectKey,并把返回值賦值給傳入?yún)?shù)的userId屬性,然后執(zhí)行insert語(yǔ)句。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持服務(wù)器之家。
原文鏈接:https://segmentfault.com/a/1190000014699207