ORA-01400本质是Oracle将空字符串""视作NULL,违反NOT NULL约束;常见原因包括Java字段为null、MyBatis漏判空字符串、主键未赋值或序列未触发,须在业务层统一处理空值或调整数据库设计。
ORA-01400 错误本质是字段值缺失,不是 Java 层面的空指针
java 报出 ora-01400: cannot insert null into ("owner"."table_name"."column_name"),说明 oracle 在执行 insert 时发现某列被设为 not null,但实际传入了 null(或空字符串 "",oracle 中二者等价)。这不是 java 的 nullpointerexception,而是数据库约束拦截——jdbc 已把语句发过去了,oracle 拒绝落地。
常见诱因包括:
- Java 实体类字段为
null,且未做非空校验或默认值填充 - 前端传参为空字符串
"",后端未转成null或占位符,直接塞进 PreparedStatement - MyBatis 的
<if test="xxx != null">漏判了空字符串,导致该字段根本没出现在 INSERT 语句中 - 主键/外键字段依赖序列(如
SEQ_ID.NEXTVAL),但 SQL 写成了硬编码NULL或没触发序列
INSERT 前必须检查 NOT NULL 字段的实际值
不要只看 Java 对象是否 null,要确认最终绑定到 JDBC 的值是否合规。Oracle 对 "" 和 NULL 不加区分,一律视作违反 NOT NULL 约束。
实操建议:
- 对所有
NOT NULL字段,在 DAO 层或 Service 层做显式校验:if (obj.getName() == null || obj.getName().trim().isEmpty()) { throw new IllegalArgumentException("name 不能为空"); } - 若业务允许“未填写”,改用明确占位符(如
"N/A"、"UNKNOWN"),而非留空或传null - 使用 MyBatis 时,避免用
<if test="name != null">控制字段插入——它放过空字符串;改用<if test="name != null and name.trim() != ''"> - 对数字/时间类型字段,注意
0、new Date(0)是否符合业务语义,别误当“有效默认值”
主键或自增字段没赋值是最常见的漏点
ORA-01400 在主键列上高频出现,尤其当表设计用序列 + 触发器,但 Java 层仍试图手动插入 NULL 或跳过该字段。
立即学习“Java免费学习笔记(深入)”;
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
关键判断点:
- 查建表语句:
DESCRIBE TABLE_NAME或SELECT column_name, nullable FROM all_tab_columns WHERE table_name = 'TABLE_NAME',确认哪些字段真不可为空 - 查主键生成方式:是否有对应序列?触发器是否启用?
SELECT trigger_name FROM all_triggers WHERE table_name = 'TABLE_NAME' AND triggering_event LIKE '%INSERT%' - 若用 JPA/Hibernate,确认
@GeneratedValue(strategy = GenerationType.SEQUENCE)配置正确,且@SequenceGenerator名称与 DB 序列一致 - 若手写 SQL,主键字段必须显式写成
SEQ_NAME.NEXTVAL,不能留空或填NULL
空字符串在 Oracle 中就是 NULL,这点必须硬记
这是和 MySQL/PostgreSQL 最大差异点:Oracle 把长度为 0 的字符串自动转为 NULL。所以即使你传了 "",Oracle 插入时也当作 NULL 处理,触发 ORA-01400。
应对方式只有两个可靠路径:
- 业务层统一拦截:所有 String 类型参数,在入库前调用
StringUtils.defaultString(str, "N/A")或类似逻辑,把null和""都转成可控值 - 数据库层妥协:把字段改为允许
NULL,并在 Java 层用Optional<String>或明确注释表示“可选”,查询时用IS NULL而非= ''
绕开这个行为的 hack(如插空格)不可取——破坏数据语义,且后续 LIKE 查询、索引效率都受影响。

















