目录
1、需求内容
有一个很常见的需求,即添加记录后获取添加后的主键ID,特别是在一次前端调用中需要插入多个表的场景。除了添加单条记录时获取主键值,有时候可能需要获取批量添加记录时各记录的主键值,MyBatis从3.3.1版本开始支持批量添加记录并返回各记录主键字段值。
比如我在做这个员工管理系统的时候,由于user和role是多对多关系,且user主键是自增的,所有我们没办法提前知晓这个user_id,所以插入的时候,就需要先插入user,然后再找到刚插入的id拿出来,再插入中间表user_role,这样才能将表关系对应起来,才能算一个完整的插入的过程。
问题是对于刚刚插入到数据库中的一条记录,我怎么知道这个user_id,再怎么拿出来,再插入中间表user_role。(当然一种做法是,执行完一条插入数据后,再执行查询的操作,不推荐这种方法),其实如果用的是MyBatis框架,本身就有这个功能。
2、实现方法
2.1 方法
在MyBatis中要用到insert和update元素下的3个属性:分别是useGeneratedKeys,keyProperty和keyColumn。这三个属性(仅对 insert 语句和 update语句 有用)。
2.2 含义
useGeneratedKeys:这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键,默认值:false。如果将useGeneratedKeys设置为true,在执行添加记录之后可以获取到数据库自动生成的主键ID。
keyProperty:唯一标记一个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey 子元素设置它的键值,默认:unset。对应它的值是Java对象中的属性值。
keyColumn:通过生成的键值设置表中的列名,这个设置仅在某些数据库(像 PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。对应它的值是数据库中表的字段值。
3、具体实现
在MyBatis中,允许设置名称为“useGeneratedKeys”参数存在3个位置:
1、在settings元素中设置useGeneratedKeys参数
2、在xml映射器中设置useGeneratedKeys参数
3、在接口映射器中设置useGeneratedKeys参数
在不同位置设置的useGeneratedKeys参数,最终结果相同,但是影响范围不同。
3.1 在settings元素中设置
在settings元素中设置useGeneratedKeys参数
在settings元素中设置useGeneratedKeys是一个全局参数,但是只会对接口映射器产生影响,对xml映射器不起效。
<settings>
<!-- 允许JDBC支持自动生成主键,需要驱动兼容。 如果设置为true则这个设置强制使用自动生成主键,
尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。 -->
<setting name="useGeneratedKeys" value="true" />
</settings>
此时,在接口映射中添加记录之后将返回主键ID。
public interface TacticsMapper {
// 受全局useGeneratedKeys参数控制,添加记录之后将返回主键id
@Insert("insert into op_tactics_info (name,remark, create_time,update_time) values (#{name},#{remark},#{createTime},#{updateTime})")
Integer insertTactics(Tactics tactics);
}
但是,请注意如果此时在接口映射器中又明确设置了useGeneratedKeys参数,那么注解映射器中的useGeneratedKeys参数值将覆盖settings元素中设置的全局useGeneratedKeys参数值。
例如:先在settings元素中设置全局useGeneratedKeys参数值为true,再在接口映射器中设置useGeneratedKeys参数值为false,添加记录之后将不能返回注解ID。
public interface TacticsMapper {
// 在接口映射器中设置的useGeneratedKeys参数值将会覆盖在settings元素中设置全局useGeneratedKeys参数值
@Options(useGeneratedKeys = false, keyProperty = "id", keyColumn = "id")
@Insert("insert into op_tactics_info (name,remark, create_time,update_time) values (#{name},#{remark},#{createTime},#{updateTime})")
Integer insertTactics(Tactics tactics);
}
另外,在settings元素中设置的全局useGeneratedKeys参数对于xml映射器无效。如果希望在xml映射器中执行添加记录之后返回主键ID,则必须在xml映射器中明确设置useGeneratedKeys参数值为true。
3.2 在xml映射器中配置
在xml映射器中配置useGeneratedKeys参数
<insert id="insertTactics" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
insert into op_tactics_info
(tactics_name,remark, create_time,update_time)
values
(#{tacticsName},#{remark},#{createTime},#{updateTime})
</insert>
xml映射器中配置的useGeneratedKeys参数只会对xml映射器产生影响,且在settings元素中设置的全局useGeneratedKeys参数值对于xml映射器不产生任何作用。
3.3 在接口映射器中设置
在接口映射器中设置useGeneratedKeys参数
// 设置useGeneratedKeys为true,返回数据库自动生成的记录主键id
@Options(useGeneratedKeys = false, keyProperty = "id", keyColumn = "id")
@Insert("insert into op_tactics_info (name,remark, create_time,update_time) values (#{name},#{remark},#{createTime},#{updateTime})")
Integer insertTactics(Tactics tactics);
注意: 在接口映射器中设置的useGeneratedKeys参数会覆盖在<settings>
元素中设置的对应参数值。
【参考资料】