MyBatis @SelectKey注解用法详细介绍
备注:如果指定了 @SelectKey 注解,那么 MyBatis 就会忽略掉由 @Options 注解所设置的生成主键。
很多时候新增一条数据,仅仅知道操作结果(新增成功)是远远不够的,更多的时候需要这条新增数据的主键,以便下文使用。通常的办法是:先新增,后将其查询出来,这在MySQL中有专门的函数可以获取到:SELECT LAST_INSERT_ID(),顾名思义,此函数的目的是获取最后插入的自增ID。
mybatis中通过一些设置可以将insert的数据的主键返回,直接拿到新增数据的主键,以便后续使用,主要有两种场景,分别针对mysql和oracle进行设置。
使用@Options注解(userGeneratedKeys和keyProperty属性)获取主键
我们可以使用@Options注解的userGeneratedKeys和keyProperty属性让数据库产生auto_increment(自增长)列的值,然后将生成的值设置到输入参数对象的属性中。
@Insert("INSERT INTO STUDENTS(NAME,EMAIL,ADRESS,PHONE)
VALUES(#{name},#{email},#{address},#{phone})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insertStudent(Student student);
这里ID列值将会通过MySQL数据库自动生成。并且生成的值将会被设置到student对象的Id属性中。
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
mapper.insertStudent(student);
int studentId = student.getId();
使用@SelectKey注解获取主键
有一些数据库如Oracle,并不支持AUTO_INCREMENT列属性,它使用序列(SEQUENCE)来产生主键的值。我们可以使用@SelectKey注解来为任意SQL语句来指定主键值,作为主键列的值。
假设我们有一个名为STUD_ID_SEQ的序列来生成ID主键值。
@Insert("INSERT INTO STUDENTS(ID,NAME,EMAIL,ADDR,PHONE)
VALUES(#{id},#{name},#{email},#{address},#{phone})")
@SelectKey(statement="SELECT STUD_ID_SEQ.NEXTVAL FROM DUAL",
keyProperty="id", resultType=int.class, before=true)
int insertStudent(Student student);
这里我们使用了@SelectKey来生成主键值,并且存储到了student对象的id属性上。由于我们设置了before=true,该语句将会在执行INSERT语句之前执行。
如果你使用序列作为触发器来设置主键值,我们可以在INSERT语句执行后,从sequence_name.currval获取数据库产生的主键值。
@Insert("INSERT INTO STUDENTS(NAME,EMAIL,ADDR,PHONE)
VALUES(#{name},#{email},#{address},#{phone})")
@SelectKey(statement="SELECT STUD_ID_SEQ.CURRVAL FROM DUAL",
keyProperty="id", resultType=int.class, before=false)
int insertStudent(Student student);
补充说明:非自增主键的获取方法
设计表的时候有两种主键,一种自增主键,一般为int类型,一种为非自增的主键,例如用uuid等。下面来讲讲非自增主键的获取方法。大致一样,些许不同。
@Insert("INSERT INTO STUDENTS(ID,NAME,EMAIL,ADDR,PHONE)
VALUES(#{id},#{name},#{email},#{address},#{phone})")
@SelectKey(statement="SELECT UUID()",
keyProperty="id", resultType=String.class, before=true)
int insertStudent(Student student);
跟自增主键方式相比,这里的不同之处只有三点:
- insert语句需要写id字段了,并且values里面也不能省略。
- selectKey的order属性需要写成BEFORE,因为这样才能将生成的uuid主键放入到user中,这样后面的insert的values里面的id才不会获取为空。
- 跟自增主键相比就这点区别,这里的获取主键id的方式为select uuid() 。