Spring Boot2.7升级3.3后hibernate.ddl-auto=validate校验错误原因咨询
问题背景
原应用基于Spring Boot 2.7.x + Hibernate 5.6,引入同版本仅包含数据库实体类的项目,设置spring.jpa.hibernate.ddl-auto = validate后启动正常。升级至Spring Boot 3.3.2(配套Hibernate 6.5),同时更新实体项目的jakarta.persistence命名空间并升级Spring Boot版本后,启动出现两处校验错误:
1. 日期字段错误
实体中java.util.Date类型字段对应MySQL的date列,报错信息:
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: wrong column type encountered in column [value_date] in table [movements]; found [date (Types#DATE)], but expecting [datetime(6) (Types#TIMESTAMP)]
2. 枚举字段错误
实体中定义的字段:
@Column(name = "field_id") @Enumerated(EnumType.ORDINAL) private Field field;
(Field为枚举类)对应MySQL的int(11)列,报错信息:
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: wrong column type encountered in column [field_id] in table [field_lookup]; found [int (Types#INTEGER)], but expecting [tinyint (Types#TINYINT)]
问题:该错误的根源是Spring Boot还是Hibernate?
答案
这些校验错误的根源是Hibernate 6.x的类型映射规则变更,与Spring Boot无关。
日期字段错误原因
Hibernate 5.x中,java.util.Date字段会根据上下文自动映射为DATE或TIMESTAMP类型;但Hibernate 6.x调整了默认映射规则,将java.util.Date默认映射为TIMESTAMP类型,而你的数据库列是DATE类型,因此校验时出现类型不匹配。
枚举字段错误原因
Hibernate 6.x对@Enumerated(EnumType.ORDINAL)的默认数据库类型映射做了修改:Hibernate 5.x默认用INTEGER对应枚举序数,而Hibernate 6.x默认将枚举序数映射为TINYINT,与现有数据库的int(11)列类型不匹配,触发校验错误。
解决建议
- 日期字段:给字段添加
@Temporal(TemporalType.DATE)注解,明确指定映射为DATE类型;或者改用java.time.LocalDate替代java.util.Date(推荐,符合JPA 3.x的最佳实践)。 - 枚举字段:在
@Column注解中显式指定列类型,比如@Column(name = "field_id", columnDefinition = "int(11)");或者添加Hibernate配置hibernate.type.preferred_enum_ordinal_type=integer,恢复旧版本的映射行为。
内容的提问来源于stack exchange,提问作者d00d

