JPA OneToMany 列表找不到应该继承的 mappedBy 属性
JPA OneToMany list does not find mappedBy property which should be inherited
我们目前正在处理一些要求,我们必须将一些相似的实体(汽车图片、宠物图片、假日图片等)添加到数据库中,这些实体都属于一个所有者(人)。我们不直接 link 字节数组,而是使用引用。稍后可能会添加更多的图片类型,因此为了保持较低的复杂性,我们希望直接将其 link 转换为 Java Classes 以便我们可以使用 instance of
和类似的东西。我们想将 @Inheritance
用于超级 class PictureRef
,它包含公共属性以及对人的 links。然后是另一个实体 Person
,它将包含这些子 class 的列表。这是具有 mappedBy
属性的 OneToMany
关系。此 mappedBy
属性未知,因此 JPA returns 我们遇到此错误:
Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown
target entity property: de.company.project.somepackages.PictureRef.person
in de.company.project.somepackages.Person.picturesOfCars
我认为下面的代码最能说明这一点。为了便于阅读,我删除了其他属性以及 getters/setters 和 id 序列。
1) 所有 JPA 实体都派生自一个包含 id 和审计值的抽象实体。这与其他 subclasses 一起正常工作,所以我认为这 class 不会导致问题。
Class 抽象实体
@MappedSuperclass
public abstract class AbstractEntity implements Serializable {
@Id
// Sequence definition removed
private Long id;
// other values are following //
}
2) 然后我们有一个superclass,它必须包含一个共同的属性。所有派生的classes都要写成一个table(因为它们看起来真的很相似)。我们还将拥有直接与该实体一起工作的业务逻辑,例如按id加载或删除。
Class 图片参考
@Entity
@Table(name = "t_picture_ref")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "picture_type")
// Sequence Definition removed
public class PictureRef extends AbstractEntity {
// common attributes, e.g. name or link to file //
@ManyToOne
@JoinColumn(name = "person_id")
private Person person;
}
3) 那么至少有两个子class。更多即将到来。它们将包含仅与此类图片相关的属性。
Class CarPictureRef
@Entity
@DiscriminatorValue("car")
public class CarPictureRef extends PictureRef {
@Column(name="licence_plate_visible")
private boolean licensePlateVisible;
}
Class 假日图片参考
@Entity
@DiscriminatorValue("holiday")
public class HolidayPictureRef extends PictureRef {
@Column(name="weather_condition")
private String weatherCondition;
}
4) 然后是拥有/上传所有这些图片的人。该人有每种图片的列表,因为应用程序对它们的处理方式非常不同。每个列表都包含具体的 subclasses,但是对于 mappedBy
属性,我们使用来自 superclass PictureRef
的 person
。或许这种继承是不可能的?
Class 人
@Entity
@Table(name = "t_person")
// Sequence Definition removed
public class Person extends AbstractEntity {
@OneToMany(mappedBy = "person", targetEntity = CarPictureRef.class)
private List<CarPictureRef> picturesOfCars;
@OneToMany(mappedBy = "person", targetEntity = HolidayPictureRef.class)
private List< HolidayPictureRef> picturesOfHolidays;
// a lot of other fields following //
}
一种解决方法可能是只将具有所有属性的所有内容存储在一个 table 中(无论如何我们都想这样做),然后也只存储在一个实体中 PictureRef
。然后我们将在后端编写应用程序逻辑来评估 pictureType
并为相应的业务案例创建新的 classes。但这似乎有点难看——我希望有一个针对这个常见用例的 JPA 解决方案?
也许我们只是缺少一个或多个注释?
为了完整起见,我添加了完整的堆栈跟踪。我们正在使用 Hibernate 4.3.8.Final 并且在部署到 WildFly 8.2.0.Final.
期间发生错误
21:19:24,283 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 88) MSC000001: Failed to start service jboss.persistenceunit."Example-1.0-SNAPSHOT.war#ExamplePU": org.jboss.msc.service.StartException in service jboss.persistenceunit."Example-1.0-SNAPSHOT.war#ExamplePU": javax.persistence.PersistenceException: [PersistenceUnit: ExamplePU] Unable to build Hibernate SessionFactory
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.run(PersistenceUnitServiceImpl.java:172) [wildfly-jpa-8.2.0.Final.jar:8.2.0.Final]
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.run(PersistenceUnitServiceImpl.java:117) [wildfly-jpa-8.2.0.Final.jar:8.2.0.Final]
at java.security.AccessController.doPrivileged(Native Method) [rt.jar:1.8.0_25]
at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:474) [wildfly-security-manager-1.0.0.Final.jar:1.0.0.Final]
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.run(PersistenceUnitServiceImpl.java:182) [wildfly-jpa-8.2.0.Final.jar:8.2.0.Final]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_25]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_25]
at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_25]
at org.jboss.threads.JBossThread.run(JBossThread.java:122) [jboss-threads-2.1.1.Final.jar:2.1.1.Final]
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: ExamplePU] Unable to build Hibernate SessionFactory
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:1239) [hibernate-entitymanager-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.access0(EntityManagerFactoryBuilderImpl.java:120) [hibernate-entitymanager-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.perform(EntityManagerFactoryBuilderImpl.java:855) [hibernate-entitymanager-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.perform(EntityManagerFactoryBuilderImpl.java:845) [hibernate-entitymanager-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:398) [hibernate-core-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:844) [hibernate-entitymanager-4.3.7.Final.jar:4.3.7.Final]
at org.jboss.as.jpa.hibernate4.TwoPhaseBootstrapImpl.build(TwoPhaseBootstrapImpl.java:44) [jipijapa-hibernate4-3-1.0.1.Final.jar:]
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.run(PersistenceUnitServiceImpl.java:154) [wildfly-jpa-8.2.0.Final.jar:8.2.0.Final]
... 8 more
Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown target entity property:
de.company.project.somepackages.PictureRef.person in de.company.project.somepackages.Person.picturesOfCars
at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:768) [hibernate-core-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.cfg.annotations.CollectionBinder.secondPass(CollectionBinder.java:728) [hibernate-core-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:70) [hibernate-core-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1697) [hibernate-core-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1426) [hibernate-core-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1846) [hibernate-core-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.perform(EntityManagerFactoryBuilderImpl.java:852) [hibernate-entitymanager-4.3.7.Final.jar:4.3.7.Final]
... 13 more
21:19:24,291 ERROR [org.jboss.as.controller.management-operation] (management-handler-thread - 2) JBAS014613: Operation ("deploy") failed - address: ([("deployment" => "Example-1.0-SNAPSHOT.war")]) - failure description: {"JBAS014671: Failed services" => {"jboss.persistenceunit.\"Example-1.0-SNAPSHOT.war#ExamplePU\"" => "org.jboss.msc.service.StartException in service jboss.persistenceunit.\"Example-1.0-SNAPSHOT.war#ExamplePU\": javax.persistence.PersistenceException: [PersistenceUnit: ExamplePU] Unable to build Hibernate SessionFactory
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: ExamplePU] Unable to build Hibernate SessionFactory
Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: de.company.project.somepackages.PictureRef.person in de.company.project.somepackages.Person.picturesOfCars"}}
21:19:24,292 ERROR [org.jboss.as.server] (management-handler-thread - 2) JBAS015870: Deploy of deployment "Example-1.0-SNAPSHOT.war" was rolled back with the following failure message:
{"JBAS014671: Failed services" => {"jboss.persistenceunit.\"Example-1.0-SNAPSHOT.war#ExamplePU\"" => "org.jboss.msc.service.StartException in service jboss.persistenceunit.\"Example-1.0-SNAPSHOT.war#ExamplePU\": javax.persistence.PersistenceException: [PersistenceUnit: ExamplePU] Unable to build Hibernate SessionFactory
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: ExamplePU] Unable to build Hibernate SessionFactory
Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: de.company.project.somepackages.PictureRef.person in de.company.project.somepackages.Person.picturesOfCars"}}
您触及了 JPA 规范中没有详细介绍的区域。 2.11 的 JPA 规范指出:
An entity may inherit from another entity class. Entities support
inheritance, polymorphic associations, and polymorphic queries.
确切的支持是什么还没有定义。
当您尝试将 @OneToMany
映射到继承 @ManyToOne
关系的子类时......
public class Person extends AbstractEntity {
@OneToMany(mappedBy = "person", targetEntity = CarPictureRef.class)
private List<CarPictureRef> picturesOfCars;
@OneToMany(mappedBy = "person", targetEntity = HolidayPictureRef.class)
private List< HolidayPictureRef> picturesOfHolidays;
...
}
Hibernate 抱怨
mappedBy reference an unknown target entity property
因此,在将 mappedBy 解析为子类时,Hibernate 不允许继承字段(在本例中为 person
)。然而,关系定义中有足够的信息来解析这些关系,EclipseLink 做得很好。
可以将 @ManyToOne
从超级 (PictureRef)
转移到具体子类(CarPictureRef
等)
@Entity
public class CarPictureRef extends PictureRef {
@ManyToOne
@JoinColumn(name = "person_id")
private Person person;
...
}
使用此解决方案,您可以将 Person
中的 @OneToMany
映射保持原样。不幸的是,这在 Hibernate 中不起作用,因为 Hibernate 将查找具有正确 person_ID 的任何子实体(在本例中为任何 pictureRef
子类),然后抱怨找到的类型是错误的类型
org.hibernate.WrongClassException: Object [id=55] was not of the specified subclass.
同样,Hibernate 可以通过使用 Discriminator 列来解决这个问题,但它没有,而且,这是 EclipseLink 做的事情。
解决此问题的方法是为每个子类指定不同的连接列,这意味着随着每个新子类的出现,您需要修改 table,我认为这并不理想。
使用 Hibernate,您可以将 PictureRef
超类作为您的@OneToMany 关系的目标,这样 Person 实体就变成了;
@Entity
@Table(name = "t_person")
// Sequence Definition removed
public class Person extends AbstractEntity {
@OneToMany(mappedBy = "person", targetEntity = PictureRef.class)
private List<PictureRef> pictures;
...
}
然后您将拥有一个 PictureRef 列表,这些 PictureRef 将是任何子类。您可以测试列表中的项目并设置包含每个所需子类型的瞬态字段。所以在这个程度上,Hibernate 支持多态关联,但是 eclipseLink 做的更多,所以要注意可移植性问题。
对于类似的情况,可以通过使用@JoinColumn 而不是mappedBy 和@where(子句="discriminator value")来解决它。
但是奇怪的是,这个问题从2008年就开始出现了,为什么到现在还没有解决。
check this
我们目前正在处理一些要求,我们必须将一些相似的实体(汽车图片、宠物图片、假日图片等)添加到数据库中,这些实体都属于一个所有者(人)。我们不直接 link 字节数组,而是使用引用。稍后可能会添加更多的图片类型,因此为了保持较低的复杂性,我们希望直接将其 link 转换为 Java Classes 以便我们可以使用 instance of
和类似的东西。我们想将 @Inheritance
用于超级 class PictureRef
,它包含公共属性以及对人的 links。然后是另一个实体 Person
,它将包含这些子 class 的列表。这是具有 mappedBy
属性的 OneToMany
关系。此 mappedBy
属性未知,因此 JPA returns 我们遇到此错误:
Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown
target entity property: de.company.project.somepackages.PictureRef.person
in de.company.project.somepackages.Person.picturesOfCars
我认为下面的代码最能说明这一点。为了便于阅读,我删除了其他属性以及 getters/setters 和 id 序列。
1) 所有 JPA 实体都派生自一个包含 id 和审计值的抽象实体。这与其他 subclasses 一起正常工作,所以我认为这 class 不会导致问题。
Class 抽象实体
@MappedSuperclass
public abstract class AbstractEntity implements Serializable {
@Id
// Sequence definition removed
private Long id;
// other values are following //
}
2) 然后我们有一个superclass,它必须包含一个共同的属性。所有派生的classes都要写成一个table(因为它们看起来真的很相似)。我们还将拥有直接与该实体一起工作的业务逻辑,例如按id加载或删除。
Class 图片参考
@Entity
@Table(name = "t_picture_ref")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "picture_type")
// Sequence Definition removed
public class PictureRef extends AbstractEntity {
// common attributes, e.g. name or link to file //
@ManyToOne
@JoinColumn(name = "person_id")
private Person person;
}
3) 那么至少有两个子class。更多即将到来。它们将包含仅与此类图片相关的属性。
Class CarPictureRef
@Entity
@DiscriminatorValue("car")
public class CarPictureRef extends PictureRef {
@Column(name="licence_plate_visible")
private boolean licensePlateVisible;
}
Class 假日图片参考
@Entity
@DiscriminatorValue("holiday")
public class HolidayPictureRef extends PictureRef {
@Column(name="weather_condition")
private String weatherCondition;
}
4) 然后是拥有/上传所有这些图片的人。该人有每种图片的列表,因为应用程序对它们的处理方式非常不同。每个列表都包含具体的 subclasses,但是对于 mappedBy
属性,我们使用来自 superclass PictureRef
的 person
。或许这种继承是不可能的?
Class 人
@Entity
@Table(name = "t_person")
// Sequence Definition removed
public class Person extends AbstractEntity {
@OneToMany(mappedBy = "person", targetEntity = CarPictureRef.class)
private List<CarPictureRef> picturesOfCars;
@OneToMany(mappedBy = "person", targetEntity = HolidayPictureRef.class)
private List< HolidayPictureRef> picturesOfHolidays;
// a lot of other fields following //
}
一种解决方法可能是只将具有所有属性的所有内容存储在一个 table 中(无论如何我们都想这样做),然后也只存储在一个实体中 PictureRef
。然后我们将在后端编写应用程序逻辑来评估 pictureType
并为相应的业务案例创建新的 classes。但这似乎有点难看——我希望有一个针对这个常见用例的 JPA 解决方案?
也许我们只是缺少一个或多个注释?
为了完整起见,我添加了完整的堆栈跟踪。我们正在使用 Hibernate 4.3.8.Final 并且在部署到 WildFly 8.2.0.Final.
期间发生错误21:19:24,283 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 88) MSC000001: Failed to start service jboss.persistenceunit."Example-1.0-SNAPSHOT.war#ExamplePU": org.jboss.msc.service.StartException in service jboss.persistenceunit."Example-1.0-SNAPSHOT.war#ExamplePU": javax.persistence.PersistenceException: [PersistenceUnit: ExamplePU] Unable to build Hibernate SessionFactory
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.run(PersistenceUnitServiceImpl.java:172) [wildfly-jpa-8.2.0.Final.jar:8.2.0.Final]
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.run(PersistenceUnitServiceImpl.java:117) [wildfly-jpa-8.2.0.Final.jar:8.2.0.Final]
at java.security.AccessController.doPrivileged(Native Method) [rt.jar:1.8.0_25]
at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:474) [wildfly-security-manager-1.0.0.Final.jar:1.0.0.Final]
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.run(PersistenceUnitServiceImpl.java:182) [wildfly-jpa-8.2.0.Final.jar:8.2.0.Final]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_25]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_25]
at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_25]
at org.jboss.threads.JBossThread.run(JBossThread.java:122) [jboss-threads-2.1.1.Final.jar:2.1.1.Final]
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: ExamplePU] Unable to build Hibernate SessionFactory
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:1239) [hibernate-entitymanager-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.access0(EntityManagerFactoryBuilderImpl.java:120) [hibernate-entitymanager-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.perform(EntityManagerFactoryBuilderImpl.java:855) [hibernate-entitymanager-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.perform(EntityManagerFactoryBuilderImpl.java:845) [hibernate-entitymanager-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:398) [hibernate-core-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:844) [hibernate-entitymanager-4.3.7.Final.jar:4.3.7.Final]
at org.jboss.as.jpa.hibernate4.TwoPhaseBootstrapImpl.build(TwoPhaseBootstrapImpl.java:44) [jipijapa-hibernate4-3-1.0.1.Final.jar:]
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.run(PersistenceUnitServiceImpl.java:154) [wildfly-jpa-8.2.0.Final.jar:8.2.0.Final]
... 8 more
Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown target entity property:
de.company.project.somepackages.PictureRef.person in de.company.project.somepackages.Person.picturesOfCars
at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:768) [hibernate-core-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.cfg.annotations.CollectionBinder.secondPass(CollectionBinder.java:728) [hibernate-core-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:70) [hibernate-core-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1697) [hibernate-core-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1426) [hibernate-core-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1846) [hibernate-core-4.3.7.Final.jar:4.3.7.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.perform(EntityManagerFactoryBuilderImpl.java:852) [hibernate-entitymanager-4.3.7.Final.jar:4.3.7.Final]
... 13 more
21:19:24,291 ERROR [org.jboss.as.controller.management-operation] (management-handler-thread - 2) JBAS014613: Operation ("deploy") failed - address: ([("deployment" => "Example-1.0-SNAPSHOT.war")]) - failure description: {"JBAS014671: Failed services" => {"jboss.persistenceunit.\"Example-1.0-SNAPSHOT.war#ExamplePU\"" => "org.jboss.msc.service.StartException in service jboss.persistenceunit.\"Example-1.0-SNAPSHOT.war#ExamplePU\": javax.persistence.PersistenceException: [PersistenceUnit: ExamplePU] Unable to build Hibernate SessionFactory
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: ExamplePU] Unable to build Hibernate SessionFactory
Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: de.company.project.somepackages.PictureRef.person in de.company.project.somepackages.Person.picturesOfCars"}}
21:19:24,292 ERROR [org.jboss.as.server] (management-handler-thread - 2) JBAS015870: Deploy of deployment "Example-1.0-SNAPSHOT.war" was rolled back with the following failure message:
{"JBAS014671: Failed services" => {"jboss.persistenceunit.\"Example-1.0-SNAPSHOT.war#ExamplePU\"" => "org.jboss.msc.service.StartException in service jboss.persistenceunit.\"Example-1.0-SNAPSHOT.war#ExamplePU\": javax.persistence.PersistenceException: [PersistenceUnit: ExamplePU] Unable to build Hibernate SessionFactory
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: ExamplePU] Unable to build Hibernate SessionFactory
Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: de.company.project.somepackages.PictureRef.person in de.company.project.somepackages.Person.picturesOfCars"}}
您触及了 JPA 规范中没有详细介绍的区域。 2.11 的 JPA 规范指出:
An entity may inherit from another entity class. Entities support inheritance, polymorphic associations, and polymorphic queries.
确切的支持是什么还没有定义。
当您尝试将 @OneToMany
映射到继承 @ManyToOne
关系的子类时......
public class Person extends AbstractEntity {
@OneToMany(mappedBy = "person", targetEntity = CarPictureRef.class)
private List<CarPictureRef> picturesOfCars;
@OneToMany(mappedBy = "person", targetEntity = HolidayPictureRef.class)
private List< HolidayPictureRef> picturesOfHolidays;
...
}
Hibernate 抱怨
mappedBy reference an unknown target entity property
因此,在将 mappedBy 解析为子类时,Hibernate 不允许继承字段(在本例中为 person
)。然而,关系定义中有足够的信息来解析这些关系,EclipseLink 做得很好。
可以将 @ManyToOne
从超级 (PictureRef)
转移到具体子类(CarPictureRef
等)
@Entity
public class CarPictureRef extends PictureRef {
@ManyToOne
@JoinColumn(name = "person_id")
private Person person;
...
}
使用此解决方案,您可以将 Person
中的 @OneToMany
映射保持原样。不幸的是,这在 Hibernate 中不起作用,因为 Hibernate 将查找具有正确 person_ID 的任何子实体(在本例中为任何 pictureRef
子类),然后抱怨找到的类型是错误的类型
org.hibernate.WrongClassException: Object [id=55] was not of the specified subclass.
同样,Hibernate 可以通过使用 Discriminator 列来解决这个问题,但它没有,而且,这是 EclipseLink 做的事情。
解决此问题的方法是为每个子类指定不同的连接列,这意味着随着每个新子类的出现,您需要修改 table,我认为这并不理想。
使用 Hibernate,您可以将 PictureRef
超类作为您的@OneToMany 关系的目标,这样 Person 实体就变成了;
@Entity
@Table(name = "t_person")
// Sequence Definition removed
public class Person extends AbstractEntity {
@OneToMany(mappedBy = "person", targetEntity = PictureRef.class)
private List<PictureRef> pictures;
...
}
然后您将拥有一个 PictureRef 列表,这些 PictureRef 将是任何子类。您可以测试列表中的项目并设置包含每个所需子类型的瞬态字段。所以在这个程度上,Hibernate 支持多态关联,但是 eclipseLink 做的更多,所以要注意可移植性问题。
对于类似的情况,可以通过使用@JoinColumn 而不是mappedBy 和@where(子句="discriminator value")来解决它。 但是奇怪的是,这个问题从2008年就开始出现了,为什么到现在还没有解决。 check this