目錄
1、需求內容
有一個很常見的需求,即添加記錄後獲取添加後的主鍵ID,特別是在一次前端調用中需要插入多個表的場景。除了添加單條記錄時獲取主鍵值,有時候可能需要獲取批量添加記錄時各記錄的主鍵值,MyBatis從3.3.1版本開始支持批量添加記錄並返回各記錄主鍵字段值。
比如我在做這個員工管理系統的時候,由於user和role是多對多關係,且user主鍵是自增的,所有我們沒辦法提前知曉這個user_id,所以插入的時候,就需要先插入user,然後再找到剛插入的id拿出來,再插入中間表user_role,這樣才能將表關係對應起來,才能算一個完整的插入的過程。
問題是對於剛剛插入到數據庫中的一條記錄,我怎麼知道這個user_id,再怎麼拿出來,再插入中間表user_role。(當然一種做法是,執行完一條插入數據後,再執行查詢的操作,不推薦這種方法),其實如果用的是MyBatis框架,本身就有這個功能。
2、實現方法
2.1 方法
在MyBatis中要用到insert和update元素下的3個屬性:分別是useGeneratedKeys,keyProperty和keyColumn。這三個屬性(僅對 insert 語句和 update語句 有用)。
2.2 含義
useGeneratedKeys:這會令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法來取出由數據庫內部生成的主鍵,默認值:false。如果將useGeneratedKeys設置爲true,在執行添加記錄之後可以獲取到數據庫自動生成的主鍵ID。
keyProperty:唯一標記一個屬性,MyBatis 會通過 getGeneratedKeys 的返回值或者通過 insert 語句的 selectKey 子元素設置它的鍵值,默認:unset。對應它的值是Java對象中的屬性值。
keyColumn:通過生成的鍵值設置表中的列名,這個設置僅在某些數據庫(像 PostgreSQL)是必須的,當主鍵列不是表中的第一列的時候需要設置。對應它的值是數據庫中表的字段值。
3、具體實現
在MyBatis中,允許設置名稱爲“useGeneratedKeys”參數存在3個位置:
1、在settings元素中設置useGeneratedKeys參數
2、在xml映射器中設置useGeneratedKeys參數
3、在接口映射器中設置useGeneratedKeys參數
在不同位置設置的useGeneratedKeys參數,最終結果相同,但是影響範圍不同。
3.1 在settings元素中設置
在settings元素中設置useGeneratedKeys參數
在settings元素中設置useGeneratedKeys是一個全局參數,但是隻會對接口映射器產生影響,對xml映射器不起效。
<settings>
<!-- 允許JDBC支持自動生成主鍵,需要驅動兼容。 如果設置爲true則這個設置強制使用自動生成主鍵,
儘管一些驅動不能兼容但仍可正常工作(比如 Derby)。 -->
<setting name="useGeneratedKeys" value="true" />
</settings>
此時,在接口映射中添加記錄之後將返回主鍵ID。
public interface TacticsMapper {
// 受全局useGeneratedKeys參數控制,添加記錄之後將返回主鍵id
@Insert("insert into op_tactics_info (name,remark, create_time,update_time) values (#{name},#{remark},#{createTime},#{updateTime})")
Integer insertTactics(Tactics tactics);
}
但是,請注意如果此時在接口映射器中又明確設置了useGeneratedKeys參數,那麼註解映射器中的useGeneratedKeys參數值將覆蓋settings元素中設置的全局useGeneratedKeys參數值。
例如:先在settings元素中設置全局useGeneratedKeys參數值爲true,再在接口映射器中設置useGeneratedKeys參數值爲false,添加記錄之後將不能返回註解ID。
public interface TacticsMapper {
// 在接口映射器中設置的useGeneratedKeys參數值將會覆蓋在settings元素中設置全局useGeneratedKeys參數值
@Options(useGeneratedKeys = false, keyProperty = "id", keyColumn = "id")
@Insert("insert into op_tactics_info (name,remark, create_time,update_time) values (#{name},#{remark},#{createTime},#{updateTime})")
Integer insertTactics(Tactics tactics);
}
另外,在settings元素中設置的全局useGeneratedKeys參數對於xml映射器無效。如果希望在xml映射器中執行添加記錄之後返回主鍵ID,則必須在xml映射器中明確設置useGeneratedKeys參數值爲true。
3.2 在xml映射器中配置
在xml映射器中配置useGeneratedKeys參數
<insert id="insertTactics" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
insert into op_tactics_info
(tactics_name,remark, create_time,update_time)
values
(#{tacticsName},#{remark},#{createTime},#{updateTime})
</insert>
xml映射器中配置的useGeneratedKeys參數只會對xml映射器產生影響,且在settings元素中設置的全局useGeneratedKeys參數值對於xml映射器不產生任何作用。
3.3 在接口映射器中設置
在接口映射器中設置useGeneratedKeys參數
// 設置useGeneratedKeys爲true,返回數據庫自動生成的記錄主鍵id
@Options(useGeneratedKeys = false, keyProperty = "id", keyColumn = "id")
@Insert("insert into op_tactics_info (name,remark, create_time,update_time) values (#{name},#{remark},#{createTime},#{updateTime})")
Integer insertTactics(Tactics tactics);
注意: 在接口映射器中設置的useGeneratedKeys參數會覆蓋在<settings>
元素中設置的對應參數值。
【參考資料】