有時候我們不僅僅是通過返回 int 影響行數來確定數據是否插入成功就行了,因為我們總是會用到這個剛剛插入的自增主鍵,比如主子表入庫,子表需要主表的 id,那這個時候我們再去數據庫查就顯得有點 low 了~
關於數據庫中主鍵的生成無非就兩種,一種是 int 類型的自增,一種是 varchar 類型的非自增(例如:UUID)。
在 Mybatis 中,提供了 selectKey 來幫我們獲取新增的主鍵,同時通過 selectKey 可以很容易的實現自增還是非自增規則的需求。
首先看一下 Mybatis 中 selectKey 的屬性說明:
| 屬性 | 描述 |
|---|---|
| keyProperty | selectKey 語句結果應該被設置的目標屬性(也就是自增的主鍵字段,比如id)。 |
| resultType | 結果的類型,比如java.lang.Integer,java.lang.String等。MyBatis 通常可以算出來,但是寫上也沒有問題。MyBatis 允許任何簡單類型用作主鍵的類型,包括字符串。 |
| order | 這可以被設置為 BEFORE 或 AFTER。如果設置為 BEFORE,那么它會首先選擇主鍵,設置 keyProperty 然后執行插入語句。如果設置為 AFTER,那么先執行插入語句,然后是 selectKey 元素-這和如 Oracle 數據庫相似,可以在插入語句中嵌入序列調用。 |
| statementType | 和前面的相同,MyBatis 支持 STATEMENT,PREPARED 和 CALLABLE 語句的映射類型,分別代表 PreparedStatement 和 CallableStatement 類型。 |
下面從 Oracle 跟 MySQL 分別舉例說明。
1. Oracle
<insert id="insertUserInfo" parameterType="club.sscai.entity.UserInfo">
<selectKey keyProperty="id" resultType="java.lang.Integer" order="BEFORE">
select SEQ_T_USER_INFO.NEXTVAL from dual
</selectKey>
insert into "T_USER_INFO"
<trim prefix="(" suffix=")" suffixOverrides=",">
ID,USER_NAME,PASSWORD,PHONE,STATUS,
<if test="remark != null">
REMARK,
</if>
CREATE_TIME,UPDATE_TIME,UPDATE_BY
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
#{id,jdbcType=DECIMAL}, #{userName,jdbcType=VARCHAR},
#{PASSWORD,jdbcType=VARCHAR},#{PHONE,jdbcType=VARCHAR},#{status,jdbcType=CHAR},
<if test="remark != null">
#{remark,jdbcType=VARCHAR},
</if>
#{createTime,jdbcType=TIMESTAMP},#{updateTime,jdbcType=TIMESTAMP}, #{updateBy,jdbcType=VARCHAR}
</trim>
</insert>
如上代碼主要是向 T_USER_INFO 表插入用戶數據,parameterType 值傳入的是實體對象,這里也可以是 map 或者是其他對象。
其中 的 keyProperty 值對應生成主鍵的字段,resultType 表示要返回的主鍵的類型,在這里我用的 Integer 類型,你也可以用 String,只要跟實體的字段對應即可。order 屬性需要注意一下,不同於支持自增類型的 MySQL 等數據庫,Oracle 需要設置設置為 after 才能取到正確的值,但是如果要從序列化中取值,則需要設置為 befor,否則會報錯,我上邊的代碼是從序列中取值所以設置為 befor。
標簽內的 SEQ_T_USER_INFO 表示該表的序列化,關於創建表序列化代碼如下(SEQ_T_USER_INFO 名稱隨便起,盡量規范即可):
create sequence SEQ_T_USER_INFO
minvalue 1
maxvalue 9999999999999999999999999999
start with 1
increment by 1
cache 20;
字符串 uuid 類型非自增主鍵, selectKey 如下:
<selectKey keyProperty="id" resultType="java.lang.String" order="BEFORE">
select sys_guid() from dual
</selectKey>
2. MySQL
<insert id="insertUserInfo" parameterType="club.sscai.entity.UserInfo" >
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.string">
select uuid()
</selectKey>
insert into T_USER_INFO
(id, user_name, PASSWORD,PHONE,STATUS,REMARK,CREATE_TIME,UPDATE_TIME,UPDATE_BY)
values
(#{id},#{userName},#{password},#{phone},#{status},省略...)
</insert>
上方是 MySQL 通過 select uuid() 就能得到 uuid 字符串,實現 UUID 字符串形式的主鍵生成。如果需要 int 類型則如下所示:
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
select LAST_INSERT_ID()
</selectKey>
至此,關於主鍵生成基本已經完事了,再額外補充關於 order = befor、after 的應用。
如果你使用的是 UUID() 這種形式的,建議選擇 order = befor,而 order = after 更適合返回自增(int)類型的主鍵。
我創建了一個用來記錄自己學習之路的公眾號,感興趣的小伙伴可以關注一下微信公眾號:niceyoo
