MyBatis
一、基础入门:MyBatis 获取自增主键ID的最小配置

要快速实现MyBatis keyProperty(主键在Java对象中的属性名)、order(执行时机,AFTER或BEFORE)、resultType(主键数据类型)。下面以MySQL和Oracle为例,分别展示XML和注解两种配置方式:
1. MySQL场景:XML配置示例
MySQL的自增主键(AUTO_INCREMENT)在数据插入后生成,因此order需设置为AFTER:
<insert id="insertUser" parameterType="com.crocodilejava.entity.User">
INSERT INTO user(username, password, create_time)
VALUES(#{username}, #{password}, #{createTime})
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
SELECT LAST_INSERT_ID()
</selectKey>
</insert>
调用mapper方法后,自增的ID会自动设置到传入的User对象的id属性中:
User user = new User("test", "123456", LocalDateTime.now());
userMapper.insertUser(user);
System.out.println("插入后的主键ID:" + user.getId()); // 输出自动生成的ID
2. Oracle场景:XML配置示例
Oracle依赖序列(SEQUENCE)生成主键,需在插入前获取序列值,因此order设置为BEFORE:
<insert id="insertUser" parameterType="com.crocodilejava.entity.User">
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.Long">
SELECT USER_SEQ.NEXTVAL FROM DUAL
</selectKey>
INSERT INTO user(id, username, password, create_time)
VALUES(#{id}, #{username}, #{password}, #{createTime})
</insert>
这里3. 注解方式配置 除了XML,MyBatis也支持用@SelectKey注解实现,适合偏好注解开发的场景:
@Insert("INSERT INTO user(username, password, create_time) VALUES(#{username}, #{password}, #{createTime})")
@SelectKey(
keyProperty = "id",
resultType = Long.class,
before = false, // 对应order="AFTER"
statement = "SELECT LAST_INSERT_ID()"
)
int insertUser(User user);
二、跨数据库适配:从MySQL到Oracle的配置差异
不同数据库的主键生成机制差异极大,MyBatis order属性和查询语句的适配,鳄鱼java整理了生产环境常用数据库的配置方案:
| 数据库 | 主键生成方式 | order属性 | |
|---|---|---|---|
| MySQL | AUTO_INCREMENT | AFTER | SELECT LAST_INSERT_ID() |
| Oracle | SEQUENCE | BEFORE | SELECT SEQ_NAME.NEXTVAL FROM DUAL |
| PostgreSQL | SERIAL/IDENTITY | AFTER | SELECT currval(pg_get_serial_sequence('user', 'id')) |
| SQL Server | IDENTITY | AFTER | SELECT SCOPE_IDENTITY() |
| SQLite | AUTOINCREMENT | AFTER | SELECT last_insert_rowid() |
鳄鱼java技术团队曾服务某企业级用户,在从MySQL迁移到Oracle的过程中,因未修改order属性导致主键获取失败,将order="AFTER"改为order="BEFORE"并替换为序列查询语句后,问题彻底解决。
三、对比useGeneratedKeys:什么时候该用?
MyBatis还提供了useGeneratedKeys属性简化自增主键获取,很多开发者会混淆两者的适用场景。鳄鱼java通过3个维度对比两者差异:
1. 配置复杂度对比
- useGeneratedKeys:配置更简洁,仅需在useGeneratedKeys="true" keyProperty="id",适合支持自增主键的数据库(如MySQL、SQL Server);
- :配置更繁琐,但支持所有数据库,尤其是非自增主键场景(如Oracle序列、UUID生成)。
2. 功能灵活性对比
- useGeneratedKeys:仅能获取数据库自增生成的主键,无法处理插入后需要获取其他字段(如数据库默认生成的创建时间戳)、复合主键、序列生成主键等场景;
- :支持任意SQL查询,可在插入前后执行任意逻辑,比如插入后获取当前数据库时间,或插入前生成UUID主键:
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String"> SELECT REPLACE(UUID(), '-', '') FROM DUAL </selectKey>
3. 性能差异对比
两者性能几乎无差异,useGeneratedKeys直接调用JDBC原生方法获取主键,执行一次额外的SQL查询,但JDBC对数据库连接的复用会抵消这部分开销。鳄鱼java实测:在1000次批量插入场景下,两者的总耗时差异仅为0.5%。
总结:如果仅适配支持自增主键的数据库,优先用useGeneratedKeys;如果需要跨数据库兼容、处理非自增主键或复杂逻辑,必须选择MyBatis
四、源码溯源:的底层执行逻辑
要彻底理解MyBatis
- SQL解析阶段:MyBatis解析
标签时,会将 标签解析为 SelectKeyGenerator对象,保存keyProperty、order等属性; - 执行时机判断:根据
order属性,SelectKeyGenerator分为BEFORE和AFTER两种类型: -BEFORE类型:在执行插入SQL前,先执行中的
版权声明
本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。





