研究这个的原由是应为需求对一张表新增了一个有默认值的字段,然后调用插入接口的时候发现这个字段没有传默认值但是还是以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
)时使用,否则可能破坏数据库默认值逻辑。