Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 自定义鉴别器的Hibernate错误类异常_Java_Hibernate_Jpa - Fatal编程技术网

Java 自定义鉴别器的Hibernate错误类异常

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

我有一个具体的JPA实体超类,映射为
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

即使您定义了no
DiscriminatorValue
,也只有一个:

如果
鉴别器值
注释不正确 指定,并且使用了鉴别器列 特定于提供程序的函数将用于生成值 表示实体类型。如果
鉴别器类型
字符串
,鉴别器值默认为 实体名称

(摘自)

但是您可以在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
。有关此主题的更多信息,请查看此项。

谢谢。这并不是我所希望的答案:-),但仍然有助于确认,确实没有一种有效的方式来做我想做的事情。