赞
踩
大家好,我们今天来看下mysql中selectKey的用法。
返回自增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();
以上就是本文讨论的,欢迎大家指出问题,共同进步
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。