Oracle 21c 默认不支持 VARCHAR2(255) 存储 UUID 的根本原因是其对 VARCHAR2 隐式长度限制变化及方言适配不足:未显式指定长度时,JDBC 驱动可能按 1 字节处理,且旧版方言(如 Oracle12cDialect)误映射为 RAW(16) 或忽略长度,导致 36 位 UUID 截断或 ORA-12899 报错。
Oracle 21c 默认不支持 VARCHAR2(255) 存储 UUID 字符串
根本原因不是 hibernate 本身,而是 oracle 21c 对 varchar2 类型的隐式长度限制变化:当未显式指定长度时,某些驱动或方言会默认生成 varchar2 而非 char(36) 或 varchar2(36),导致插入 32 位或带连字符的 36 位 uuid(如 "f81d4fae-7dec-11d0-a765-00a0c91e6bf6")时被截断或报错 ora-12899: value too large for column。
- Oracle 21c 的 JDBC 驱动(ojdbc11+)对未声明长度的
VARCHAR2字段可能按 1 字节默认处理,而非传统 4000 字节 - Hibernate 默认用
string类型映射 UUID,在无显式列定义时,会生成VARCHAR2,但长度由方言推断,而Oracle21cDialect尚未完全适配 UUID 场景 - 如果你用的是
@GeneratedValue(generator = "uuid2"),Hibernate 实际生成的是 32 位十六进制字符串(不含连字符),长度为 32;但若业务代码传入带连字符的 36 位格式,就会越界
hibernate.dialect 配置错误导致 DDL 生成异常
用错方言是常见误操作。Oracle 21c 必须使用 org.hibernate.dialect.Oracle21cDialect(Hibernate 5.6.15+ / 6.1.0+),旧版如 Oracle12cDialect 或 Oracle10gDialect 会误判类型映射规则,把 uuid 映射成 RAW(16) 或直接忽略长度约束,最终建表失败或字段不可写。
- 检查配置项是否为
hibernate.dialect=org.hibernate.dialect.Oracle21cDialect,而不是靠 IDE 自动补全选的“Oracle”模糊选项 - 若用 Spring Boot,确认
spring.jpa.database-platform值为org.hibernate.dialect.Oracle21cDialect,而非oracle(该别名在较新版本中已弃用) - 启动时加
hibernate.hbm2ddl.debug=true,观察日志里实际执行的CREATE TABLE语句中 UUID 字段是否为VARCHAR2(36)或CHAR(36)
@Column(length = 36) 被忽略的典型场景
即使写了 @Column(length = 36),也可能无效——因为 Hibernate 在 Oracle 下优先信任方言对类型的“硬编码映射”,而非注解。尤其当实体字段类型是 String、又没配 @Type(type = "uuid-char") 时,@Column 的 length 对 VARCHAR2 不起作用。
- 正确做法:显式指定 Hibernate 内置 UUID 类型,例如
@Type(type = "uuid-char")(对应 36 位带连字符)或@Type(type = "uuid-binary")(对应 16 字节RAW) - 若坚持用
String字段,必须配合@Column(columnDefinition = "VARCHAR2(36 CHAR)"),注意CHAR单位(非字节),否则中文环境下可能出错 - XML 映射同理:
<property name="id" type="string"><column name="id" sql-type="VARCHAR2(36 CHAR)"/></property>
UUID 字段设为 NOT NULL 后 insert 报 ORA-01400
这是最隐蔽的坑:Hibernate 在 flush 时若发现字段为 NOT NULL 但值为 null,不会报空指针,而是静默跳过赋值,最终触发 Oracle 的非空约束失败,错误信息是 ORA-01400: cannot insert NULL into ("SCHEMA"."TABLE"."ID")。但日志里往往只显示 SQL 执行失败,不提示哪一列为空。
- 排查重点不是数据库约束,而是 Java 实体字段是否真的被赋值——特别是用了 Lombok
@Builder或 MapStruct 时,UUID 字段容易漏初始化 - 加断点看
session.save(entity)前实体的id字段是否为null;若用merge(),更要确认原对象 ID 是否被清空 - 避免依赖 Hibernate 自动生成(如
@GeneratedValue)与手动设置混用:一旦配置了<generator class="uuid.hex"/>,手动设的id就会被忽略,见知识库中多条“手动设置 id 无效”的记录
CHAR vs BYTE)、JDBC 驱动版本、Hibernate 方言实现三者之间那几处没文档明说的边界行为。


















