大家都知道像mysql,serveSql這樣的數據庫都提供有自增id的功能,而像oracle這樣的數據庫採取的是序列的方式來實現自增主鍵的,所以如果通過mybatis插入一條數據後返回主鍵id的方式也是不同的,網上有很多種說法,大都沒說太明白,下面舉個例子,詳細說明一下,避免再入坑
建表語句
CREATE TABLE sys_student
(
id int PRIMARY KEY NOT NULL AUTO_INCREMENT,
name varchar(50) COMMENT '名字'
);
ALTER TABLE sys_student COMMENT = '學生表';
一、mysql
mysql有自增功能,可以採用useGeneratedKeys="true"開啓判斷是否是自增ID, keyProperty="id" 指定插入數據後自增ID返回時賦值給實體類的那個屬性(這裏是id屬性)
<insert id="insertStudent" useGeneratedKeys="true" keyProperty="id">
insert into sys_student(name) values(#{name})
</insert>
二、oracle
創建序列語句:
CREATE SEQUENCE student_seq
INCREMENT BY 1
START WITH 1
NOMAXVALUE
NOCYCLE ;
創建觸發器:
CREATE OR REPLACE TRIGGER student_trigger
BEFORE INSERT ON sys_student
FOR EACH ROW
BEGIN
SELECT student_seq.NEXTVAL INTO :NEW.id FROM DUAL;
END;
這裏要說明一下,通常oracle實現自增,是通過觸發器實現的。先建一個序列,再建一個觸發器,每次在執行插入時,都會觸發觸發器實現自動加1。
像Oracle數據庫採用序列來作爲自增主鍵,可以通過 selectKey子來獲取主鍵值
<insert id="insertStudent" useGeneratedKeys="false">
<selectKey resultType="java.lang.Integer" keyProperty="id" order="BEFORE">
select student_seq.nextval from dual
</selectKey>
insert into sys_student(name) values(#{name})
</insert>
網上很多都是這樣說的,但是最後的你可能會發現每次都自增2,而不是自增1,那麼問題出在哪了呢?
問題就出在了這句‘ select student_seq.nextval from dual’,這句的意思就是每執行一次,自增序列都會加1,如果你的oracle是通過觸發器實現的,那麼恭喜你,你會發現每插入一條數據,都會自增2,之所以這樣是因爲你執行了兩次 student_seq.nextval 。
還有一種就是利用max()函數,這種也是有問題的,而這個問題還不太容易發現,如果剛開始你的表裏一條數據都沒有,第一次執行,你會發現返回自增主鍵id,居然是null,這個問題應該也很好解決,把order="BEFORE" 改成 order="AFTER",沒準能行,我沒有試,有興趣可以自己試一下。
<insert id="insertStudent" useGeneratedKeys="false">
<selectKey resultType="java.lang.Integer" keyProperty="id" order="BEFORE">
select max(id) from sys_student
</selectKey>
insert into sys_student(name) values(#{name})
</insert>
正確的方法是什麼呢?
如果你有需要返回自增後的主鍵id,如果已經建了觸發器,那麼就刪掉觸發器,每次執行插入時,手動實現自增,如下,注意標紅的地方,如果沒有需要要返回自增id,那麼採用觸發器實現自增是完全沒有問題的。
刪除觸發器:
DROP TRIGGER student_trigger;
<insert id="insertStudent" useGeneratedKeys="false">
<selectKey resultType="java.lang.Integer" keyProperty="id" order="AFTER">
select student_seq.currval from dual
</selectKey >
insert into sys_student(id,name) values(student_seq.nextval,#{name})
</insert>
如果覺得有用,麻煩關注一下我的公衆號,謝謝