java JPA@OneToOne在映射到具有子类的抽象@实体时抛出错误
当一个实体映射到另一个在其子类上有直接实现的实体时,我遇到了一个问题。请参见下面的示例映射:
@Entity
class Location {
@OneToOne
@JoinColumn(...)
private Person person;
}
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="person_type",discriminatorType=DiscriminatorType.STRING)
abstract class Person {
}
@Entity
@DiscriminatorValue("M")
class Man extends Person {
...
}
@Entity
@DiscriminatorValue("W")
class Woman extends Person {
...
}
现在,这是我在数据库表中的内容:
位置表: id=1,个人id=1 人员表: id=1,person\u type=“M”
当我使用实体管理器检索位置时,hibernate抛出一个异常,表示我无法实例化抽象类或接口
Location location = entityManager.find(Location.class, 1L);
Hibernate抛出以下错误:
javax.persistence.PersistenceException: org.hibernate.InstantiationException: Cannot instantiate abstract class or interface: Person
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:630)
at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:195)
at ......
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98)
at org.unitils.UnitilsJUnit4TestClassRunner$TestListenerInvokingMethodRoadie.runTestMethod(UnitilsJUnit4TestClassRunner.java:174)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
at org.unitils.UnitilsJUnit4TestClassRunner$TestListenerInvokingMethodRoadie.runBeforesThenTestThenAfters(UnitilsJUnit4TestClassRunner.java:156)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
at org.unitils.UnitilsJUnit4TestClassRunner.invokeTestMethod(UnitilsJUnit4TestClassRunner.java:95)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.unitils.UnitilsJUnit4TestClassRunner.access$000(UnitilsJUnit4TestClassRunner.java:44)
at org.unitils.UnitilsJUnit4TestClassRunner$1.run(UnitilsJUnit4TestClassRunner.java:62)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.unitils.UnitilsJUnit4TestClassRunner.run(UnitilsJUnit4TestClassRunner.java:68)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
# 1 楼答案
正如我在上面的评论中所指出的,我在EclipseLink上也尝试过同样的方法,而且效果很好
在创建了一些测试数据之后,我清除了数据库中person条目的鉴别器值,现在我在尝试加载相关位置时遇到了类似的异常。EclipseLink的信息更具描述性:
映射似乎是有效的,因此,除非数据“损坏”(正如您所说,在您的情况下并非如此),否则它可能是一个bug,或者至少是Hibernate中的不同行为
# 2 楼答案
我运行了与此类似的代码,但有几个不同之处。首先,我将抽象类放在接口后面。其次,我明确定义了@OnetoOne映射的targetEntity。例如:
为了清晰起见,我将Person抽象类重命名为“AbstractPerson”。花了不少时间才让它工作起来,我希望它能解决你的问题
# 3 楼答案
我发现,如果实体类实现
Serializable
,这种问题就会自行解决# 4 楼答案
这对我来说很管用,使用hibernate作为持久性提供者
# 5 楼答案
我收到了一条类似的错误消息,其结构如下:
以一个具体的儿童为例
以及一个类,该类有一个引用抽象类的字段:
以下更改解决了我的问题:
@OneToOne
更改为@OneToOne(cascade = CascadeType.ALL)
@GeneratedValue
更改为@GeneratedValue(strategy = GenerationType.TABLE)
更新:我还发现在将RealPerson对象链接到某个类之前,我没有保存它。现在我首先保存实例,不再需要
cascade
属性# 6 楼答案
从The Java EE 6 Tutorial - Entity Inheritence
因此,您必须用
@Entity
注释Person
类,以便通过@OneToOne
将其与Location
关联,这似乎是正确的来自@MappedSuperclass javadoc
所以不能在Person上使用
@MappedSuperclass
,然后将其映射到@OneToOne
,因为将没有Person表看起来你使用的JPA注释是正确的。您是否尝试过@Martin Klinge为
Person
类提供一个虚拟鉴别器值的建议