很多时候新增一条数据,仅仅知道操作结果(新增成功)是远远不够的,更多的时候需要这条新增数据的主键,以便下文使用。通常的办法是:先新增,后将其查询出来,这在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() 。

标签: none


添加新评论