问题描述
使用mybatis插入数据返回的主键和数据库中的不一致,实体类映射的主键自增1次,数据库主键自增2次,例如主键的当前值为1,那么下一条数据的主键应该为2,但是执行下列的配置文件对oracle数据库执行insert语句后,实体类返回2,但是数据库的主键值为3.正常应该是2。
不想看废话的,想看解决办法直接跳到最后一行。
问题分析
mapper配置文件如下
<insert id="addSourceFileData" parameterType="com.xxx.entity.SourceFile">
<selectKey resultType="java.lang.Integer" keyProperty="souid" order="before">
select arch_sourcefile_souid_seq.nextval as souid from dual
</selectKey>
insert into ARCH_SOURCEFILE(
<trim suffixOverrides=",">
<if test="souname != null">souname,</if>
<if test="souexname != null">souexname</if>
</trim>
)values(
<trim suffixOverrides=",">
<if test="souname != null">#{souname},</if>
<if test="souexname != null">#{souexname}</if>
</trim>
)
</insert>
上面的配置文件中会执行以下两条sql,每执行一次都会造成主键的自增一次,所以最后映射到实体的主键是自增1次的
select arch_sourcefile_souid_seq.currval as souid from dual
insert into ARCH_SOURCEFILE(souname,souexname) values (#{souname},#{souexname})
因为以上这段代码,同时会执行两次select arch_sourcefile_souid_seq.currval as souid from dual,可以看到触发器中也有同样的一条语句,因为在执行insert操作的时候会触发触发器执行一次select arch_sourcefile_souid_seq.currval as souid from dual,所以也会造成主键自增,
触发器代码如下
create or replace trigger arch_sourcefile_trigger
before insert on arch_sourcefile
for each row
begin
select arch_sourcefile_souid_seq.nextval into:new.souid from dual;
end arch_sourcefile_trigger;
解决办法就是不要去获取序列的下一个值,而是取当前的值,将配置文件中的**nextval 改为currval **:
<selectKey resultType="java.lang.Integer" keyProperty="souid" order="before">
select ARCH_SOURCEFILE_SOUID_SEQ.currval as souid from dual
</selectKey>
由于selectKey 这个标签的属性order=“before”,那么在运行的时候会提示:
也就是说你要先执行insert才能获取当前的序列值(主键值),所以还需要改selectKey 这个标签的属性为order="after"在insert语句后执。
最后的mapper配置文件改为:
<insert id="addSourceFileData" parameterType="com.xxx.entity.SourceFile">
<selectKey resultType="java.lang.Integer" keyProperty="souid" order="after">
select arch_sourcefile_souid_seq.currval as souid from dual
</selectKey>
insert into ARCH_SOURCEFILE(
<trim suffixOverrides=",">
<if test="souname != null">souname,</if>
<if test="souexname != null">souexname</if>
</trim>
)values(
<trim suffixOverrides=",">
<if test="souname != null">#{souname},</if>
<if test="souexname != null">#{souexname}</if>
</trim>
)
</insert>
总结
改mapper文件的nextval 改为currval ,mapper文件的selectKey 设置为order="after"