Java 自定义鉴别器的Hibernate错误类异常
我有一个具体的JPA实体超类,映射为Java 自定义鉴别器的Hibernate错误类异常,java,hibernate,jpa,Java,Hibernate,Jpa,我有一个具体的JPA实体超类,映射为InheritanceType.JOINED,使用鉴别器列,并有两个子类实体,用附加属性扩展这个超类 @Entity @Inheritance(strategy = InheritanceType.JOINED) @DiscriminatorColumn(name = "TYPE") public class BaseEntity { // . . . } @Entity @DiscriminatorValue("SUBTYPE") public c
InheritanceType.JOINED
,使用鉴别器列,并有两个子类实体,用附加属性扩展这个超类
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "TYPE")
public class BaseEntity {
// . . .
}
@Entity
@DiscriminatorValue("SUBTYPE")
public class SubclassEntity extends BaseEntity {
// . . .
}
在某些情况下,我希望指定额外的鉴别器值,而不必为每种类型显式定义子类(也就是说,不是每个“BaseEntity”都指定额外的属性来保证子类/单独的表)。该策略在数据库设计和Java类层次结构中都能很好地工作,但是Hibernate JPA不允许这样做,并抛出一个ErrorClassException
,因为没有映射到鉴别器的子类:
Caused by: org.hibernate.WrongClassException: Object [id=entity-1] was not of the specified subclass [com.so.jpa.BaseEntity] : Discriminator: custom-1
at org.hibernate.loader.plan.exec.process.internal.EntityReferenceInitializerImpl.getConcreteEntityTypeName(EntityReferenceInitializerImpl.java:415)
at org.hibernate.loader.plan.exec.process.internal.EntityReferenceInitializerImpl.hydrateEntityState(EntityReferenceInitializerImpl.java:217)
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.readRow(AbstractRowReader.java:90)
at org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails$EntityLoaderRowReader.readRow(EntityLoadQueryDetails.java:238)
at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:112)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:121)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:85)
at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:167)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3954)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:488)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:453)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:196)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:258)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:134)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1071)
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:990)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:632)
at org.hibernate.type.EntityType.resolve(EntityType.java:424)
at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:154)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:128)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1132)
at org.hibernate.loader.Loader.processResultSet(Loader.java:992)
at org.hibernate.loader.Loader.doQuery(Loader.java:930)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:336)
at org.hibernate.loader.Loader.doList(Loader.java:2611)
at org.hibernate.loader.Loader.doList(Loader.java:2594)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2423)
at org.hibernate.loader.Loader.list(Loader.java:2418)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:501)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:371)
at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:220)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1268)
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:87)
at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:567)
at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:436)
...
在本例中,我希望Hibernate返回具体的基本实体BaseEntity
,而不是试图实例化一个子类。我在JPA规范(JSR338)中没有看到任何东西表明这是不可能的(尽管规范也没有显式地调用此场景)
有没有办法允许JPA/Hibernate在不需要子类的情况下允许自定义鉴别器类型?不幸的是,Hibernate要求每个实体类型只有一个鉴别器值。我想这与其他JPA提供者没有区别,因为对于实体类,不能定义多个
DiscriminatorValue
即使您定义了noDiscriminatorValue
,也只有一个:
如果鉴别器值
注释不正确
指定,并且使用了鉴别器列
特定于提供程序的函数将用于生成值
表示实体类型。如果鉴别器类型
为
字符串
,鉴别器值默认为
实体名称
(摘自)
但是您可以在Hibernate中定义鉴别器公式
,而不是鉴别器列
:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorFormula(
"CASE WHEN TYPE IN ('SUBTYPE', 'SUBTYPE-2', ...) THEN TYPE ELSE 'BaseEntity'")
public class BaseEntity {
// . . .
}
@Entity
@DiscriminatorValue("SUBTYPE")
public class SubclassEntity extends BaseEntity {
// ...
}
该解决方案的缺点:您需要在
BaseEntity
中声明所有子类型的鉴别器值该问题甚至有一个更简单的解决方案。您可以使用@DiscriminatorValue(“notnull”)
,如下所示:
@Entity
@DiscriminatorValue("not null")
public class MiscSubclassEntity extends BaseEntity {
// . . .
}
这样,只要找到未映射的鉴别器值,就会使用
miscsublasentity
。有关此主题的更多信息,请查看此项。谢谢。这并不是我所希望的答案:-),但仍然有助于确认,确实没有一种有效的方式来做我想做的事情。