今天做項目遇到這個問題:
在這里總結一下我的解決方法(Mybatis+Oracle):
業務邏輯是有個主表,中間表的外鍵是主表的主鍵,在插入數據到主表之后,需要返回主表的自增id到實體類(id),然后在將主表的id插入到中間表,但是運行時出現了上訴的錯誤。檢查了數據庫的表設計,原來表的通過觸發器+序列來創建自增id的,因此如下插入會出現問題:
<insert id="addToCheckGroup" parameterType="com.healthCloud.pojo.CheckGroup"> <selectKey resultType="java.lang.Integer" order="BEFORE" keyProperty="id"> select T_CHECKGROUP_SEQ.nextval from sys.dual </selectKey> INSERT INTO T_CHECKGROUP Values(#{id},#{code},#{name},#{helpCode},#{sex},#{remark},#{attention}) </insert>
出現這個問題的原因是程序在跑的時候,先觸動了觸發器,在調用上面的功能,id增加了2,並不是1.因此插入到中間表的時候id比插入到主表獲取的id大1,兩個id不一樣,就找不到主表的id,報未找到父項關鍵字的錯誤,正確的解決方法:
方法1:更改數據庫表的設計,去掉觸發器,只用序列來獲取只增id
-------------t_setmeal------------------- CREATE TABLE t_setmeal ( id NUMBER(11) NOT NULL, name VARCHAR2(500) DEFAULT NULL, code VARCHAR2(8) DEFAULT NULL, helpCode VARCHAR2(16) DEFAULT NULL, sex VARCHAR2(1) DEFAULT NULL, age VARCHAR2(32) DEFAULT NULL, price float DEFAULT NULL, remark VARCHAR2(500) DEFAULT NULL, attention VARCHAR2(500) DEFAULT NULL, img VARCHAR2(500) DEFAULT NULL, PRIMARY KEY (id) ) -- Create sequence 創建序列 create sequence T_SETMEAL_SEQ minvalue 1 -- 最小值=1 maxvalue 999999999999999999999999999 -- 指定最大值 -- 或nomaxvalue -- 沒有最大值 -- NOCYCLE; -- 不循環 start with 12 -- 從12開始 increment by 1 -- 每次遞增1 cache 20; INSERT INTO t_setmeal VALUES (T_SETMEAL_SEQ.NEXTVAL, '入職無憂體檢套餐(男女通用)', '0001', 'RZTJ', '0', '18-60', '300', '入職體檢套餐', null, 'a5e8e729-74ce-4939-bf36-9cdc02fb2ae51.jpg');
Mybatis中插入數據並返回自增id(序列)
<insert id="addToSetmeal" parameterType="com.healthCloud.pojo.Setmeal"> <selectKey resultType="java.lang.Integer" order="BEFORE" keyProperty="id" > select T_SETMEAL_SEQ.nextval from sys.dual </selectKey> insert into T_SETMEAL (id,name, code, helpCode, sex, age, price, remark, attention, img) Values(#{id},#{name}, #{code}, #{helpCode}, #{sex}, #{age}, #{price}, #{remark}, #{attention}, #{img}) </insert>
注意:沒有觸發器,需要先
SELECT T_SETMEAL_SEQ.nextval from dual;
但是id字段不能少,且手動添加數據時id不會自動增加
批量插入數據到中間表
<insert id="addToSetmealAndCheckGroup" parameterType="java.util.List"> INSERT INTO t_setmeal_checkgroup (setmeal_id,checkgroup_id) <foreach close=")" collection="Lists" item="item" index="index" open="(" separator="union all"> SELECT #{item.setmealId,jdbcType=NUMERIC}, #{item.checkgroupId,jdbcType=NUMERIC} FROM DUAL </foreach> </insert>
方法2:更改數據庫表的設計,添加觸發器,(觸發器+序列)獲取自增id
--創建觸發器 create or replace trigger T_SETMEAL_TRI before insert on T_SETMEAL REFERENCING OLD AS "OLD" NEW AS "NEW" FOR EACH ROW begin SELECT T_SETMEAL_SEQ.NEXTVAL INTO :NEW.ID FROM DUAL; end;
Mybatis中插入數據並返回自增id(觸發器+序列)
<insert id="addToSetmeal" parameterType="com.healthCloud.pojo.Setmeal"> <!--通過觸發器+序列獲取主鍵id--> <selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id" > select T_SETMEAL_SEQ.CURRVAL from sys.dual </selectKey> insert into T_SETMEAL (name, code, helpCode, sex, age, price, remark, attention, img) Values(#{name}, #{code}, #{helpCode}, #{sex}, #{age}, #{price}, #{remark}, #{attention}, #{img}) </insert> <!--批量插入到中間表--> <insert id="addToSetmealAndCheckGroup" parameterType="java.util.List"> INSERT INTO t_setmeal_checkgroup (setmeal_id,checkgroup_id) <foreach close=")" collection="Lists" item="item" index="index" open="(" separator="union all"> SELECT #{item.setmealId,jdbcType=NUMERIC}, #{item.checkgroupId,jdbcType=NUMERIC} FROM DUAL </foreach> </insert>
附帶刪除觸發器,刪除序列
DROP TRIGGER T_SETMEAL_TRI --刪除觸發器
DROP SEQUENCE T_SETMEAL_SEQ --刪除序列