mybatis插入数据后主键回填的几种方式
主键回填一般是插入一条数据,id设为自增,当插入一条记录时,并返回该记录id值
一、JDBC原生写法:
public int insert(Person person) {
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
con = DBUtils.getConnection();
ps = con.prepareStatement("INSERT INTO person(username,password,money) VALUES(?,?,?)", PreparedStatement.RETURN_GENERATED_KEYS);
ps.setObject(1, person.getUsername());
ps.setObject(2, person.getPassword());
ps.setObject(3, person.getMoney());
int i = ps.executeUpdate();
rs = ps.getGeneratedKeys();
int id = -1;
if (rs.next()) {
id = rs.getInt(1);
}
return id;
}
和普通的插入 SQL 不同之处主要体现在两个地方:
- 第一个是构造 PreparedStatement 时,多了一个参数,指定了需要主键回填。
- 在更新操作执行完成之后,调用 getGeneratedKeys ,然后又会获取到一个 ResultSet 对象,从这个游标集中就可以获取到刚刚插入数据的id。
二、mybatis方式:
1、 方式一
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
insert into t_user (name,age) values (#{name},#{age});
</insert>
这种方式就是在插入节点上添加 useGeneratedKeys 属性,同时设置接收回传主键的属性。配置完成后,我们执行一个插入操作,插入时传入一个对象,插入完成后,这个对象的 id 就会被自动赋值,值就是刚刚插入成功的id。
2、方式二
<insert id="insertUser">
<selectKey keyProperty="id" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
</selectKey>
insert into t_user (name,age) values (#{name},#{age});
</insert>
这种方式是在 insert 节点中添加 selectKey 来实现主键回填,实际上这种方式的功能更加丰富,因为 selectKey 节点中的 SQL 我们既可以在插入之前执行,也可以在插入之后执行(通过设置节点的 Order 属性为 AFTER 或者 BEFORE 可以实现),具体什么时候执行,还是要看具体的需求,如果是做主键回填,我们当然需要在插入 SQL 执行之后执行 selectKey 节点中的 SQL。
注意第二种方式一样也要通过设置 keyProperty 来指定将查询到的数据绑定到哪个属性上。
三、注解的方式:
注解可用于mapper接口方法上
1、@Options注解
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
useGeneratedKeys:开启主键回填
keyProperty:表示对象中的成员变量
keyColumn:表示数据库中的列名
2、@SelectKey注解
@SelectKey(statement = "select last_insert_id()", keyProperty = "id", before = false, resultType = long.class)
statement是要运行的SQL语句,它的返回值通过resultType来指定
before:指select语句是否在insert之前执行
select last_insert_id()也可以换成@@identity,效果一样
四、扩展:
@Options注解:
- 使用场景一:缓存
@Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE, timeout = 1000)
useCache = true表示将会缓存本次查询结果,以提高下次查询速度
flushCache = Options.FlushCachePolicy.FALSE表示查询时不刷新缓存
timeout = 10000表示查询结果缓存10000秒 - 使用场景二:主键回填

浙公网安备 33010602011771号