Hibernate 6单表继承类型识别异常:关联对象映射错误
Hibernate 6.2.7.FINAL 单表继承关联查询类型识别异常
问题背景
使用Hibernate 6.2.7.FINAL版本,该场景在Hibernate 5中可正常运行,现遇到继承类型无法识别的问题。
实体代码
基础实体类Animal
@Entity @Table(name = "ANIMAL") @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name = "ANIMAL_TYPE") @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") @JsonSubTypes({ @Type(value = Giraffe.class, name = "giraffeAnimal"), @Type(value = Tiger.class, name = "tigerAnimal") }) @org.hibernate.annotations.DiscriminatorOptions(force = true) public class Animal {}
子类Tiger
@Getter @Setter @NoArgsConstructor @Entity @DiscriminatorValue("Tiger") public class Tiger extends Animal {}
子类Giraffe
@Getter @Setter @NoArgsConstructor @Entity @DiscriminatorValue("Giraffe") public class Giraffe extends Animal {}
Main实体类
@Entity @Table(name = "MAIN") public class Main { @OneToOne(cascade = CascadeType.ALL, mappedBy = "main") private Tiger tiger; @OneToMany( mappedBy = "main", cascade = {CascadeType.PERSIST, CascadeType.MERGE}, orphanRemoval = true) private List<Giraffe> girrafes; }
问题现象与异常
当持久化包含1个Giraffe对象、无Tiger对象的Main类实例到数据库时,Animal表中数据正确,ANIMAL_TYPE鉴别器列值为Giraffe;但从数据库查询Main对象时,同一个Giraffe对象同时出现在Tiger属性和Giraffe列表中,而Tiger属性应为null。
集成测试抛出异常:
Caused by: org.hibernate.PropertyAccessException: 无法为类型[com.example.Girraffe]设置值: 'com.example.Main.Tiger'(setter方法) at org.hibernate.property.access.spi.SetterFieldImpl.set(SetterFieldImpl.java:88) at org.hibernate.property.access.spi.EnhancedSetterImpl.set(EnhancedSetterImpl.java:42) at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:4398) at org.hibernate.sql.results.graph.entity.AbstractEntityInitializer.initializeEntityInstance(AbstractEntityInitializer.java:851) at org.hibernate.sql.results.graph.entity.AbstractEntityInitializer.initializeEntity(AbstractEntityInitializer.java:811) at org.hibernate.sql.results.graph.entity.AbstractEntityInitializer.initializeInstance(AbstractEntityInitializer.java:797) at org.hibernate.sql.results.internal.InitializersList.initializeInstance(InitializersList.java:71) at org.hibernate.sql.results.internal.StandardRowReader.coordinateInitializers(StandardRowReader.java:109) at org.hibernate.sql.results.internal.StandardRowReader.readRow(StandardRowReader.java:86) at org.hibernate.sql.results.spi.ListResultsConsumer.consume(ListResultsConsumer.java:181) at org.hibernate.sql.results.spi.ListResultsConsumer.consume(ListResultsConsumer.java:33) at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.doExecuteQuery(JdbcSelectExecutorStandardImpl.java:361) at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.executeQuery(JdbcSelectExecutorStandardImpl.java:168) at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.list(JdbcSelectExecutorStandardImpl.java:93) at org.hibernate.sql.exec.spi.JdbcSelectExecutor.list(JdbcSelectExecutor.java:31) at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.lambda$new$0(ConcreteSqmSelectQueryPlan.java:109) at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.withCacheableSqmInterpretation(ConcreteSqmSelectQueryPlan.java:305) at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.performList(ConcreteSqmSelectQueryPlan.java:246) at org.hibernate.query.sqm.internal.QuerySqmImpl.doList(QuerySqmImpl.java:509) at org.hibernate.query.spi.AbstractSelectionQuery.list(AbstractSelectionQuery.java:427) at org.hibernate.query.spi.AbstractSelectionQuery.getSingleResult(AbstractSelectionQuery.java:559)
解决方案
该问题源于Hibernate 6处理单表继承关联映射时,未自动依据鉴别器值过滤关联实体类型,导致尝试将Giraffe实例赋值给Tiger属性,触发类型不匹配异常。直接有效的解决方式是在关联注解上显式添加鉴别器过滤条件:
- 为
@OneToOne的Tiger属性添加@Where注解指定鉴别器值:
@OneToOne(cascade = CascadeType.ALL, mappedBy = "main") @Where(clause = "ANIMAL_TYPE = 'Tiger'") private Tiger tiger;
- 为
@OneToMany的Giraffe列表添加@Where注解:
@OneToMany( mappedBy = "main", cascade = {CascadeType.PERSIST, CascadeType.MERGE}, orphanRemoval = true) @Where(clause = "ANIMAL_TYPE = 'Giraffe'") private List<Giraffe> girrafes;
同时需检查Animal子类中mappedBy指定的main关联字段是否正确定义,确保每个子类都有对应类型的Main关联属性。
内容的提问来源于stack exchange,提问作者Mohd Salim
相关产品推荐
相关产品推荐

