研究这个的原由是应为需求对一张表新增了一个有默认值的字段,然后调用插入接口的时候发现这个字段没有传默认值但是还是以null值入库了,数据库中设置的默认值没有生效。
通过排查之后发现是使用了insertUseGeneratedKeys 方法进行插入,此方法就算是没有给对象的某个属性赋值也是会全字段null进行插入。
以此文记录此问题以及解决的方法。
在 MyBatis 中,insert、insertSelective 和 insertUseGeneratedKeys 是常见的插入操作方法,它们的核心区别在于 字段处理方式 和 主键返回逻辑。以下是详细对比:
1. insert(全字段插入)
行为
- 全字段插入 :无论字段是否为
null,所有字段都会出现在 SQL 中。 - 主键处理 :默认不返回自增主键,除非显式配置
useGeneratedKeys。
SQL 示例
sql
INSERT INTO table (col1, col2, col3)
VALUES (#{col1}, #{col2}, #{col3});
- 如果
defaultFlag为null,SQL 会插入NULL(覆盖数据库默认值)。
适用场景
- 需要强制插入所有字段(即使为
null)。 - 表字段与实体类字段完全一致且无默认值约束。
2. insertSelective(动态插入非空字段)
行为
- 动态插入 :仅插入非
null字段,忽略值为null的字段。 - 主键处理 :默认不返回自增主键(需结合
@Options或全局配置启用)。
SQL 示例
sql
INSERT INTO table (col1, col2)
VALUES (#{col1}, #{col2});
- 如果
defaultFlag为null,该字段不会出现在 SQL 中,数据库使用默认值填充。
适用场景
- 表字段有默认值约束,希望依赖数据库填充默认值。
- 仅需插入部分字段(如避免覆盖数据库默认值)。
3. insertUseGeneratedKeys(返回自增主键)
行为
- 全字段插入 :与
insert类似,所有字段都会被插入。 - 主键处理 :返回数据库生成的自增主键(如 MySQL 的
AUTO_INCREMENT)。
SQL 示例
sql
INSERT INTO table (col1, col2, col3)
VALUES (#{col1}, #{col2}, #{col3});
- 插入后,自增主键值会回写到实体类的
id字段。
适用场景
- 需要获取插入后生成的自增主键。
- 明确需要全字段插入(即使包含
null值)。
对比总结
| 方法 | 字段处理 | 主键返回 | 适用场景 |
|---|---|---|---|
insert |
全字段插入(含 null) |
不返回 | 强制插入所有字段 |
insertSelective |
仅插入非空字段 | 不返回 | 依赖数据库默认值,部分字段插入 |
insertUseGeneratedKeys |
全字段插入(含 null) |
返回 | 需要自增主键且全字段插入 |
使用建议
-
优先使用
insertSelective适用于大多数场景,避免因插入
null覆盖数据库默认值,更符合动态业务需求。 -
需要主键时使用
insertUseGeneratedKeys若必须获取自增主键且接受全字段插入,可结合
@Options使用。 -
谨慎使用
insert仅在明确需要覆盖所有字段(包括
null)时使用,否则可能破坏数据库默认值逻辑。