背景
在企业开发中,需要获取新插入到数据库中的记录主键作为业务逻辑的一部分,那么如何获取相应的主键,是这篇博客的出发点。
上一篇博客mybatis学习笔记(六):添加用户信息中相关的配置和代码,大家注意的话有看到有一行打印获取主键的代码:
System.out.println(user.getId());
控制台中打印出来的结果为:0,事实上在数据库中插入的记录的id是一个自增id,不是0,所以如何不做一些其他配置的话,通过user.getId()
是无法获取到正确的主键信息
主键类型
主键类型分为两种:
- 自增主键
- 非自增主键
自增主键返回
mysql自增主键,执行insert提交之前自动生成一个自增主键。可以通过mysql自带函数LAST_INSERT_ID()
获取刚插入记录的自增主键。此函数是在insert之后调用此函数
映射文件
在User.xml中配置添加用户的statement
添加内容如下:
<!-- 添加增用户
parameterType:指定输入参数类型为pojo,即用户信息
${}中指定pojo的属性名,接收到pojo对象的属性值,mybatis通过OGNL获取对象的属性值
用户信息表user的id是自增主键,在sql语句中不需要写上id字段及对应的属性值
-->
<insert id="insertUser" parameterType="com.trc.qa.po.User">
<!--
将插入数据的主键返回,返回到User对象中。
keyProperty:将查询到的主键值设置到parameterType指定的对象的哪个属性
order:select last_insert_id()执行顺序,相对于insert语句来说的执行顺序,这里设置的是AFTER
resultType:指定select last_insert_id()的结果类型
select last_insert_id():得到刚insert进去记录的主键值,此方法只适用于自增主键
-->
<selectKey keyProperty="id" resultType="java.lang.Integer" order="AFTER">
select last_insert_id()
</selectKey>
INSERT INTO user (username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address})
</insert>
程序代码
参考上一篇博客mybatis学习笔记(六):添加用户信息,这里就不重复粘贴了
程序执行结果
......
[DEBUG]15:54:12,725,main,[Class]JdbcTransaction, [Method]openConnection, Opening JDBC Connection
[DEBUG]15:54:13,019,main,[Class]PooledDataSource, [Method]popConnection, Created connection 1630521067.
[DEBUG]15:54:13,020,main,[Class]JdbcTransaction, [Method]setDesiredAutoCommit, Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@612fc6eb]
[DEBUG]15:54:13,021,main,[Class]insertUser, [Method]debug, ==> Preparing: INSERT INTO user (username,birthday,sex,address) VALUES(?,?,?,?)
[DEBUG]15:54:13,075,main,[Class]insertUser, [Method]debug, ==> Parameters: 王大锤(String), 2018-07-25 15:54:12.721(Timestamp), 1(String), 河南洛阳(String)
[DEBUG]15:54:13,079,main,[Class]insertUser, [Method]debug, <== Updates: 1
[DEBUG]15:54:13,081,main,[Class]insertUser!selectKey, [Method]debug, ==> Preparing: select last_insert_id()
[DEBUG]15:54:13,081,main,[Class]insertUser!selectKey, [Method]debug, ==> Parameters:
[DEBUG]15:54:13,104,main,[Class]insertUser!selectKey, [Method]debug, <== Total: 1
[DEBUG]15:54:13,105,main,[Class]JdbcTransaction, [Method]commit, Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@612fc6eb]
17
[DEBUG]15:54:13,106,main,[Class]JdbcTransaction, [Method]resetAutoCommit, Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@612fc6eb]
[DEBUG]15:54:13,107,main,[Class]JdbcTransaction, [Method]close, Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@612fc6eb]
......
可以看到获取用户信息主键ID的值为17,跟数据库插入的记录中id的值一致
这里介绍完自增主键的使用方法之后,再介绍一下非自增主键返回如何使用
非自增主键返回(使用uuid())
使用mysql的uuid()自带函数生成主键,需要修改表中id字段类型为String,长度设置为64位。
执行思路:
先通过uuid()查询到主键,将主键输入到sql语句中
执行uuid()语句顺序相当于insert语句执行之前
创建用户信息表user_new
由于字段id不是自增主键,对应的数据类型不再是int类型,需要调整为varchar类型,为了便于后续博客的介绍,不直接修改user表,而新建一张表user_new,对应建表sql语句如下:
CREATE TABLE `user_new` (
`id` varchar(64) NOT NULL,
`username` varchar(32) NOT NULL COMMENT '用户名称',
`birthday` date DEFAULT NULL COMMENT '生日',
`sex` char(1) DEFAULT NULL COMMENT '性别',
`address` varchar(255) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';
创建用户信息UserNew的pojo
由于字段id不是自增主键,对应的数据类型不再是int类型,需要调整为varchar类型,为了便于后续博客的介绍,不直接修改之前的User pojo,新建一个UserNew,对应代码如下:
public class UserNew {
private String id;
private String username; //用户姓名
private String sex; //性别
private Date birthday; //生日
private String address; //地址
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
映射文件
在User.xml中配置对应的statement,内容如下:
<!-- 新增用户 user_new -->
<insert id="insertUserNew" parameterType="com.trc.qa.po.UserNew">
<!--
使用mysql的uuid()生成主键,相对于insert语句来说的执行顺序,这里设置的是BEFORE
执行过程:
首先通过uuid()生成主键,将主键设置到UserNew对象的id属性中,
其次在insert执行时,从user对象中取出id属性值
-->
<selectKey keyProperty="id" resultType="java.lang.String" order="BEFORE">
select uuid()
</selectKey>
INSERT INTO user_new (id,username,birthday,sex,address) VALUES(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
程序代码
//添加用户信息
@Test
public void insertUserNewTest() throws IOException {
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserNew user = new UserNew();
user.setUsername("张大锤");
user.setBirthday(new Date());
user.setSex("0");
user.setAddress("西安兵马俑");
sqlSession.insert("test.insertUserNew", user);
//提交事务
sqlSession.commit();
//获取用户信息主键
System.out.println(user.getId());
sqlSession.close();
}
程序执行结果
......
[DEBUG]16:43:43,680,main,[Class]JdbcTransaction, [Method]openConnection, Opening JDBC Connection
[DEBUG]16:43:43,955,main,[Class]PooledDataSource, [Method]popConnection, Created connection 1226622409.
[DEBUG]16:43:43,955,main,[Class]JdbcTransaction, [Method]setDesiredAutoCommit, Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@491cc5c9]
[DEBUG]16:43:43,958,main,[Class]insertUserNew!selectKey, [Method]debug, ==> Preparing: select uuid()
[DEBUG]16:43:44,001,main,[Class]insertUserNew!selectKey, [Method]debug, ==> Parameters:
[DEBUG]16:43:44,028,main,[Class]insertUserNew!selectKey, [Method]debug, <== Total: 1
[DEBUG]16:43:44,028,main,[Class]insertUserNew, [Method]debug, ==> Preparing: INSERT INTO user_new (id,username,birthday,sex,address) VALUES(?,?,?,?,?)
[DEBUG]16:43:44,036,main,[Class]insertUserNew, [Method]debug, ==> Parameters: d693867c-8fe6-11e8-b7f4-7439c01734bf(String), 张大锤(String), 2018-07-25 16:43:43.674(Timestamp), 0(String), 西安兵马俑(String)
[DEBUG]16:43:44,037,main,[Class]insertUserNew, [Method]debug, <== Updates: 1
[DEBUG]16:43:44,037,main,[Class]JdbcTransaction, [Method]commit, Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@491cc5c9]
d693867c-8fe6-11e8-b7f4-7439c01734bf
[DEBUG]16:43:44,038,main,[Class]JdbcTransaction, [Method]resetAutoCommit, Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@491cc5c9]
[DEBUG]16:43:44,039,main,[Class]JdbcTransaction, [Method]close, Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@491cc5c9]
......
对应的主键id成功返回,跟数据库插入记录的主键id一致