Mybatis 中 selectKey的用法

大家好,我们今天来看下mysql中selectKey的用法。

selectKey返回最近一次插入的id

返回自增ID

    <selectKey resultType="java.lang.Integer" keyProperty="id" order="BEFORE" >//AFTER
      SELECT LAST_INSERT_ID()
    </selectKey>  

项目中出现的问题:主子表入库时,子表需要主表中的id,当selectKey的order参数设置为BEFORE,获取到的id为0,导致向子表插入数据时出现主键重复的问题。解决方法将BEFORE改为AFTER

先看下selectKey的解释:

主要原因是因为BEFORE是先查最近插入一条的id,在进行插入,把BEFORE改为AFTER就可以解决这个问题。下面我们讨论一下为什么

我们来复现下这个问题

重启项目后第一次操作时总是会出现主键重复的问题,但是从第二操作就会神奇的成功

主表数据中最新的一条数据是applyId为210的数据,主键为自增

第一次进行数据入库

主表插入数据之后,根据SELECT LAST_INSERT_ID()  返回的applyId为0,正常来讲应该返回插入之后的主键211

图一:

由于子表插入失败,事务回滚主表中最新的一条数据还是主键为210的数据

图二:

 

第二次进行数据入库操作;操作子表插入

主表插入数据之后,根据SELECT LAST_INSERT_ID()  返回的applyId为211,正常来讲应该返回插入之后的主键212,图二中可以看到主表中并没有主键为211的数据。由此可见返回的并非插入到数据库中最近插入数据的主键,不管事务有没有提交成功,但是主键自增过,进行insert操作过,返回的就是最近执行insert中的主键。

图三:

数据库中的数据:我们发现主表中的id是212,但是子表中插入的主键是211

图五:

为什么会出现这种情况,原因是因为mysql 的select   LAST_INSERT_ID()语句。

在一个新的statement 中 执行 select     LAST_INSERT_ID() 返回为0,但是执行过一次insert语句后,再次执行select     LAST_INSERT_ID() 返回的是最新一次插入数据的id。

那么order属性设置为BEFORE这个就是先执行LAST_INSERT_ID()再去操作插入语句,而AFTER正好相反。

如果数据库中id为自增的方式,将selectKey的order参数置为AFTER才会返回正确的结果

2. 关于生成UUid 返回生成uuid

xml代码:

XML代码
<insert id="insert" parameterType="SysUser" >
< selectKey keyProperty="id" order="BEFORE" resultType="java.lang.string">
    select uuid()
</selectKey>
insert into sys_user 
    (id,  name, email, phone)
values 
    (#{id},#{name},#{email},#{phone})
</insert>

应用层代码 

SysUser user=new SysUser();
	user.setId("354646465465465464sdfasdfasdfasdf");
	user.setName("测试");
    user.setEmail("11@qq.com");
    user.setPhome("15866669999");
sysUserDao.insert(user);

 数据库结果,我们可以看出,数据库中的id并不是在应用层给赋值的那个id,而是执行select uuid() 的结果作为user的id。

关于生成uuid的方式,BEFORE是先设置完成id之后进行插入操作。

<insert id="insert" parameterType="SysUser" >
< selectKey keyProperty="id" order="AFTER" resultType="java.lang.string">
    select LAST_INSERT_ID()
</selectKey>
insert into sys_user 
    (id,  name, email, phone)
values 
    (#{id},#{name},#{email},#{phone})
</insert>

可以看到数据库中插入的id就是自己设置的id但是执行SELECT LAST _INSERT_ID()返回的始终都是0。

以上两种情况可以看出,BEFORE适合使用在设置UUID的情况,AFTER适合使用在返回自增id的情况

两者搭配的语句也不同,BEFORE===SELECT UUID()   ,AFTER===SELECT LAST_INSERT_ID(); 

以上就是本文讨论的,欢迎大家指出问题,共同进步

  • 32
    点赞
  • 113
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yangerkong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值