本文轉自:https://blog.csdn.net/yamadeee/article/details/83997122
在某些場景下,我們需要使用mybatis返回生成的主鍵值。Mybatis在insert和update標籤中就提供了這種功能。
<insert id=”indetifyId” useGeneratedKeys=”true” keyProperty=”id” keyColumn="id">
</insert>
useGeneratedKeys: 是否自動生成主鍵,默認false
keyProperty :返回的主鍵值賦給哪個屬性
keyColumn: 數據庫中的自增主鍵的列名,默認是數據庫表的第一列。當主鍵列不是表中的第一列的時候需要設置,PostgreSQL必須設置。
主鍵自動生成,取決於數據庫是否支持自增主鍵。實際上當設置了useGeneratedKeys=“true”,Mybatis會調用JDBC的getGeneratedKeys方法,並將獲取的主鍵值賦值給keyProperty 指定的屬性。
準備
Mysql數據庫
create table user(
USER_ID bigint not null auto_increment,
USER_NAME varchar(50) not null,
USER_PASSWORD varchar(30) not null,
CREATE_TIME datetime,
....
primary key(USER_ID)
)
實體
package com.test.User
public class User{
private Long userId;
private String userName;
private String userPassword;
...
setter getter....
}
mapper
public interface UserMapper{
int insertUser(User user); //新增用戶
}
Service
@Service
public UserServiceImple implements UserService{
@Autowired
UserMapper userMapper;
public Long inserUser(User user){
//user數據操作,例如加密
int inserts=userMapper.insertUser(user);
if(inserts == 0)//插入失敗
return -1L;
return user.getUserId();//返回主鍵值
}
}
獲取主鍵值
-
對於支持主鍵自增的數據庫(MySql)
<insert id=”insertUser” useGeneratedKeys=”true” keyProperty=”userId” >
insert into user(
user_name, user_password, create_time)
values(#{userName}, #{userPassword} , #{createTime, jdbcType= TIMESTAMP})
</insert>
parameterType 可以不寫,Mybatis可以推斷出傳入的數據類型。如果想要訪問主鍵,那麼應當parameterType 應當是java實體或者Map。這樣數據在插入之後 可以通過ava實體或者Map 來獲取主鍵值。上例中就是通過 getUserId獲取主鍵
user.getUserId()
2不支持主鍵自增的數據庫(Oracle)
對於像Oracle這樣的數據,沒有提供主鍵自增的功能,而是使用序列的方式獲取自增主鍵。可以使用<selectKey>標籤來獲取主鍵的值,這種方式不僅適用於不提供主鍵自增功能的數據庫,也適用於提供主鍵自增功能的數據庫。
select Key 一般的用法
<selectKey keyColumn="id" resultType="long" keyProperty="id" order="BEFORE">
</selectKey>
下面以 oracle 爲例:
創建 Oracle 序列:
-- 創建序列, 計數開始值: 1 ; 步長:1 ; 沒有最大值, 當超過最大值時 開始從頭開始計數
create sequence USER_ID INCREMENT by 1 START WITH 1 NOMAXVALUE CYCLE;
-- 獲取當前序列號加 +1
select USER_ID.nextval from dual;
-- 獲取當前序列號
select USER_ID.currval from dual;
獲取主鍵(序列號),並插入
<insert id=”insertUser” >
<selectKey keyColumn="id" resultType="long" keyProperty="userId" order="BEFORE">
SELECT TO_CHAR(SYSDATE, 'yyyymmdd') || USER_ID.nextval as id from dual
</selectKey>
insert into user(
user_id,user_name, user_password, create_time)
values(#{userId},#{userName}, #{userPassword} , #{createTime, jdbcType= TIMESTAMP})
</insert>
此時會將Oracle生成的主鍵值賦予userId變量。這個userId 就是USER對象的屬性,這樣就可以將生成的主鍵值返回了。如果僅僅是在insert語句中使用但是不返回,此時keyProperty=“任意自定義變量名”,
resultType 可以不寫。
Oracle 數據庫中的值要設置爲 BEFORE ,這是因爲 Oracle中需要先從序列獲取值,然後將值作爲主鍵插入到數據庫中。
雖然說Mybatis 官方文檔說 可以推斷出 resultType類型,但是實際操作過程中。 使用實體類的屬性字段去接受selectKey的查詢結果, 沒有指明resultType 的話拋出了類似如下的異常:A query was run and no Result Maps were found for the Mapped Statement 'insertXXXX!selectKey
擴展:
如果Mysql 使用selectKey的方式獲取主鍵,需要注意下面兩點:
order : AFTER
獲取遞增主鍵值 :SELECT LAST_INSERT_ID()