转自:https://juejin.cn/post/7013358349735428126
ast_insert_id的正确姿势
业务中,我们经常需要获取插入数据行的id,可以进行如下操作:
单元测试方法
@Test
public void testLastInsertId(){
Student record = new Student();
record.setStuCode("102");
record.setStuName("老王");
record.setStuSex("男");
record.setStuAge(18);
record.setStuDept("计科");
int id = studentMapper.insert(record);
Long lastId = record.getId();
System.out.println(lastId);
}
Dao接口方法
int insert(Student record);
Dao接口对应的xml文件
<insert id="insert" parameterType="org.balloon.model.entity.Student">
<!--
将insert插入的数据的主键返回到Student对象中;
select last_insert_id():得到刚insert进去记录的主键值,只适用于自增主键;
keyProperty:将查询到的主键值,设置到parameterType指定的对象的那个属性
order:select last_insert_id()执行顺序,相对于insert语句来说它的执行顺序;
resultType:指定select last_insert_id()的结果类型,也就是id的类型。
-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
SELECT LAST_INSERT_ID()
</selectKey>
insert into student (stu_code, stu_name, stu_sex,
stu_age, stu_dept)
values (#{stuCode,jdbcType=VARCHAR}, #{stuName,jdbcType=VARCHAR}, #{stuSex,jdbcType=VARCHAR},
#{stuAge,jdbcType=INTEGER}, #{stuDept,jdbcType=VARCHAR})
</insert>
注意:select last_insert_id()返回的id值封装在入参record中,通过record.getId()获取,而不是insert方法的返回值!
除此之外,我们还有别的方法可以获取插入数据行的id,只需要改一下对应的xml,如下:
<insert id="insert" parameterType="org.balloon.model.entity.Student" useGeneratedKeys="true" keyProperty="id">
insert into student (stu_code, stu_name, stu_sex,
stu_age, stu_dept)
values (#{stuCode,jdbcType=VARCHAR}, #{stuName,jdbcType=VARCHAR}, #{stuSex,jdbcType=VARCHAR},
#{stuAge,jdbcType=INTEGER}, #{stuDept,jdbcType=VARCHAR})
</insert>
last_insert_id的突然失效
大多数时候在Dao接口上我们会使用@Param注解定义入参,方便传递多个参数和设置别名,然而再通过record.getId()获取插入数据行的id值时却为null?
int insert(@Param("record") Student record);
此时,不用担心,我们只需要重新指定映射到的属性字段就好啦:(id -> record.id)
<insert id="insert" parameterType="org.balloon.model.entity.Student">
<selectKey keyProperty="record.id" order="AFTER" resultType="java.lang.Long">
SELECT LAST_INSERT_ID()
</selectKey>
insert into student (stu_code, stu_name, stu_sex,
stu_age, stu_dept)
values (#{record.stuCode,jdbcType=VARCHAR}, #{record.stuName,jdbcType=VARCHAR}, #{record.stuSex,jdbcType=VARCHAR},
#{record.stuAge,jdbcType=INTEGER}, #{record.stuDept,jdbcType=VARCHAR})
</insert>
或
<insert id="insert" parameterType="org.balloon.model.entity.Student" useGeneratedKeys="true" keyProperty="record.id">
insert into student (stu_code, stu_name, stu_sex,
stu_age, stu_dept)
values (#{record.stuCode,jdbcType=VARCHAR}, #{record.stuName,jdbcType=VARCHAR}, #{record.stuSex,jdbcType=VARCHAR},
#{record.stuAge,jdbcType=INTEGER}, #{record.stuDept,jdbcType=VARCHAR})
</insert>
last_insert_id的并发问题
select last_insert_id()是否存在并发问题呐,如果有两个连接,它们几乎同时做了插入操作,然后分别进行了查插入id,此时会得到两个相同的id值么?
结论:对于同一个connection对象,select last_insert_id()无并发问题!