数据库字段默认值能否生效取决于批量机制:mybatis 易因显式传 null 覆盖默认值;executortype.batch 在对象字段为 null 且表定义 default 时可生效;jdbc addbatch() 最可控,跳过字段即触发数据库默认填充。

Java 批量插入时,数据库字段默认值(如 CREATE_TIME、IS_DELETED、VERSION 等)能否被正确应用,取决于你用的是哪一层批量机制——MyBatis 的 <foreach></foreach>、ExecutorType.BATCH,还是原生 JDBC addBatch()。关键在于:**默认值由数据库在 INSERT 时自动填充,但前提是该字段不显式出现在 SQL 中;一旦你在批量语句里写了 #{xxx} 或传了 null 值,就可能覆盖默认行为。**
MyBatis 多值插入:默认值容易被“误填”
使用 <foreach></foreach> 拼接多值 INSERT(例如 INSERT INTO t(a,b,c) VALUES (?,?,?),(?,?,?))时,SQL 中每个字段都必须显式绑定参数。如果你的 Java 对象中某个字段为 null,而 XML 里仍写了 #{item.createTime},那么 JDBC 会把 null 传给数据库——MySQL 会报错(若字段 NOT NULL 且无默认值),或存入 null(破坏默认值逻辑)。
- 避免在
<foreach></foreach>中为带默认值的字段写#{...},改用<if test="item.createTime == null"></if>包裹,或直接从 SQL 中剔除该字段 - 确保数据库表定义明确:如
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,且 Java 对象对应字段设为transient或不参与映射 - 慎用
useGeneratedKeys="true":它要求所有字段显式传参,会强制绕过默认值;批量场景建议设为false
ExecutorType.BATCH + Mapper.insert():默认值兼容性好,但需配合字段填充逻辑
这种模式下,MyBatis 每次调用 mapper.insert(obj) 都是单条逻辑,SQL 是预编译的单行 INSERT(如 INSERT INTO t(a,b) VALUES (?,?))。只要你的对象中未设置默认值字段(即保持 null 或不赋值),且数据库字段有 DEFAULT 定义,MySQL 就会在执行时自动填充。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 推荐搭配 MyBatis-Plus 的
MetaObjectHandler:在插入前统一注入默认值(如createTime、createBy),确保字段非空、可映射,避免依赖数据库层兜底 - 注意线程安全:若用
SecurityContextHolder获取当前用户,务必基于TransmittableThreadLocal透传上下文,否则子线程中填充为空 - 不要在实体类 setter 中硬编码默认值(如
this.createTime = new Date()),会导致批量时每条都生成相同时间戳,失去精度
JDBC addBatch():完全可控,但需手动管理字段显隐
原生 JDBC 批处理中,SQL 固定(如 INSERT INTO t(a,b) VALUES (?,?)),哪些字段参与插入、是否留空,全由你拼 SQL 和 set 参数决定。这是对默认值控制最灵活的方式。
- 若某字段有默认值且不想传值,SQL 中就不声明它,对应
ps.setXXX()调用也跳过 - 例如表结构为
id, name, status DEFAULT 'ACTIVE', create_time DEFAULT NOW(),则 SQL 写成INSERT INTO t(id, name) VALUES (?,?),只调ps.setLong(1, id); ps.setString(2, name); - 需确保连接 URL 含
rewriteBatchedStatements=true,否则即使 SQL 正确,驱动仍可能拆成单条执行,丧失性能与默认值一致性
通用避坑提醒
无论哪种方式,以下两点直接影响默认值是否生效:
-
MySQL 的 SQL mode 影响大:如果启用了
STRICT_TRANS_TABLES,遇到NULL插入NOT NULL字段会直接报错;建议开发/测试环境关闭 strict mode,或确保字段定义含DEFAULT且应用层不传null -
字段类型与默认值匹配:比如
tinyint(1) DEFAULT 0,Java 传Boolean.FALSE可能触发类型转换失败;统一用包装类型或显式转为整型更稳妥
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










