Spring Boot3迁移后Hibernate6.1.7.FINAL插入忽略鉴别器列问题
问题:Spring Boot 3 + Hibernate 6.1.7.Final 迁移后鉴别器值插入失效
将项目从Spring Boot 2迁移至Spring Boot 3,并把Hibernate版本更新至6.1.7.Final后,创建实体时Hibernate会忽略鉴别器值的插入,导致数据库中TYPE列值为空。
实体代码示例
import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; @Getter @Setter @Entity @Table(name = Book.BOOK_TABLE_NAME) @DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING) @Inheritance(strategy = InheritanceType.JOINED) public abstract class Book { public static final String IDBOOK = "IDBOOK"; public static final String BOOK_TABLE_NAME = "BOOK"; @Id @Column(name = IDBOOK) private Long id; @Column(insertable = false, updatable = false) private String type; // 其他属性... } @Entity @DiscriminatorOptions(force = true) @DiscriminatorValue("PERIODIC") @Table(name = "PERIODIC") @PrimaryKeyJoinColumn(name = "IDPERIODIC") public class Periodic extends Book { // 子类属性... } @Entity @DiscriminatorOptions(force = true) @DiscriminatorValue("CODE") @Table(name = "CODE") @PrimaryKeyJoinColumn(name = "IDCODE") public class Code extends Book { // 子类属性... }
生成的SQL(缺少TYPE字段插入)
insert into book (...其他字段, idbook) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) Hibernate: insert into periodic (...字段, idperiodic) values (?, ?, ?, ?, ?)
问题原因分析
@Column(insertable = false, updatable = false)的限制:父类Book中的type字段标记了这两个属性,Hibernate 6在处理JOINED继承策略时,会严格遵循该配置,认为该字段不需要应用层插入。而Spring Boot 2对应的Hibernate 5.x版本对这种场景的处理更灵活,会自动插入鉴别器值,不受该配置影响。- Hibernate 6继承映射逻辑变更:Hibernate 6对鉴别器的处理逻辑做了调整,在JOINED策略下,当鉴别器字段被设置为
insertable=false时,框架默认认为该字段由数据库维护(比如默认值、触发器),不会主动注入@DiscriminatorValue指定的值。 @DiscriminatorOptions(force = true)的兼容性:该注解在Hibernate 6中的作用仅局限于查询阶段强制使用鉴别器过滤,无法覆盖insertable=false对插入行为的限制,因此无法触发鉴别器值的写入。
解决建议
- 移除父类
Book中type字段的insertable = false, updatable = false配置,因为鉴别器值由Hibernate管理,无需禁止插入和更新。 - 若需要保留该字段的只读特性,可以考虑不在实体类中映射
type字段,仅通过@DiscriminatorColumn定义鉴别器列即可,Hibernate依然会自动处理鉴别器值的插入。
内容的提问来源于stack exchange,提问作者César Castro Aroche
相关产品推荐
相关产品推荐

