子类和超类之间的双向 OneToMany 关联不起作用(JPA 与 Hibernate 3.6.7)
我有两个类,员工和经理。 Manager 扩展了 Employee,因为它是雇员的一种类型。 Employee有一个Manager的实例,它代表了一个员工有一个经理的想法。相反,经理有一组员工。有两个表,EMPLOYEE 和 MANAGER:
table EMPLOYEE
long ID
varchar NAME
long MANAGERID
table MANAGER
long ID
long EMPLOYEEID //a join on this field enables inheritance
这些类如下所示:
Employee.java(为简洁起见,省略了 setter 和 getter):
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "EMPLOYEE", schema = "TEST01")
public class Employee extends hata.util.Entity implements java.io.Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "ID", unique = true, nullable = false)
protected Long id;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "MANAGERID")
protected Manager manager;
@Column(name = "FIRSTNAME", nullable = false, length = 50)
protected String firstname;
Manager.java
@Entity
@PrimaryKeyJoinColumn(name="EMPLOYEEID")
@Table(name = "MANAGER", schema = "TEST01")
public class Manager extends Employee implements java.io.Serializable {
@OneToMany(fetch = FetchType.LAZY, mappedBy = "manager")
private Set<Employee> employees = new HashSet<Employee>(0);
我用一些员工填充了表,所有这些员工都有相同的经理,除了一名员工 - 经理。他本人没有经理。 (如果您正确理解我的意思,那么很明显,我在 manager 表中有 1 行,并且 EMPLOYEEID 引用回 EMPLOYEE 表中的一行,该行具有 null,因为它是 MANAGERID)。
因此,这个设置对我来说看起来是正确的,但是当我尝试使用以下命令查询所有 Employee 对象时:
Query q = em.createQuery("select em from Employee em");
result = (List<Employee>) q.getResultList();
我得到了一个令人讨厌的堆栈跟踪:
Caused by: org.hibernate.PropertyAccessException: Could not set a field value by Reflection setter of hata .staff.entity.Employee.manager 在 org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:151) 在 org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValues(AbstractEntityTuplizer.java:586) 在 org.hibernate.tuple.entity.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:231) 在 org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:3824) 在 org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:153) 在 org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:898) 在 org.hibernate.loader.Loader.doQuery(Loader.java:773) 在 org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:270) 在 org.hibernate.loader.Loader.doList(Loader.java:2294) 在 org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2172) 在 org.hibernate.loader.Loader.list(Loader.java:2167) 在 org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:448) 在 org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:363) 在 org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196) 在 org.hibernate.impl.SessionImpl.list(SessionImpl.java:1258) 在 org.hibernate.impl.QueryImpl.list(QueryImpl.java:102) 在 org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:236) ... 108 更多 引起:java.lang.IllegalArgumentException:无法将 hata.staff.entity.Manager 字段 hata.staff.entity.Employee.manager 设置为 hata.staff.entity.Employee 在 sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164) 在 sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168) 在 sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81) 在 java.lang.reflect.Field.set(Field.java:680) 在 org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:139) ... 124 更多
我是否编码错误,或者休眠根本无法处理这种情况?我将不胜感激任何帮助。
I have two classes, Employee and Manager. Manager extends Employee, as it is a type of employee. Employee has an instance of Manager, which represents the idea of an employee having one manager. Conversely, manager has a set of Employees. There are two tables, EMPLOYEE and MANAGER:
table EMPLOYEE
long ID
varchar NAME
long MANAGERID
table MANAGER
long ID
long EMPLOYEEID //a join on this field enables inheritance
The classes look like this:
Employee.java (setters and getters omitted for brevity):
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "EMPLOYEE", schema = "TEST01")
public class Employee extends hata.util.Entity implements java.io.Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "ID", unique = true, nullable = false)
protected Long id;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "MANAGERID")
protected Manager manager;
@Column(name = "FIRSTNAME", nullable = false, length = 50)
protected String firstname;
Manager.java
@Entity
@PrimaryKeyJoinColumn(name="EMPLOYEEID")
@Table(name = "MANAGER", schema = "TEST01")
public class Manager extends Employee implements java.io.Serializable {
@OneToMany(fetch = FetchType.LAZY, mappedBy = "manager")
private Set<Employee> employees = new HashSet<Employee>(0);
I have filled the tables with a few employees, and all of those employees have the same manager, except for one employee - the one who is the manager. He himself has no manager. (If you're following me correctly, then it should be obvious that I have 1 row in the manager table, with and EMPLOYEEID referring back to a row in the EMPLOYEE table that has null as it's MANAGERID).
So, this setup looked correct to me, however when I tried to query all Employee objects with:
Query q = em.createQuery("select em from Employee em");
result = (List<Employee>) q.getResultList();
I get a nasty stack trace:
Caused by: org.hibernate.PropertyAccessException: could not set a field value by reflection setter of hata.staff.entity.Employee.manager
at org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:151)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValues(AbstractEntityTuplizer.java:586)
at org.hibernate.tuple.entity.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:231)
at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:3824)
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:153)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:898)
at org.hibernate.loader.Loader.doQuery(Loader.java:773)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:270)
at org.hibernate.loader.Loader.doList(Loader.java:2294)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2172)
at org.hibernate.loader.Loader.list(Loader.java:2167)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:448)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:363)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1258)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:236)
... 108 more
Caused by: java.lang.IllegalArgumentException: Can not set hata.staff.entity.Manager field hata.staff.entity.Employee.manager to hata.staff.entity.Employee
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
at java.lang.reflect.Field.set(Field.java:680)
at org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:139)
... 124 more
Did I code this wrong, or can hibernate simply not handle this scenario? I'd appreciate any assistance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
管理器中的
EMPLOYEEID
列不应该存在。@PrimaryKeyJoinColumn
表示主键也是连接列。因此,MANAGER
中的ID
列既是EMPLOYEE
的主键也是外键。当然,注释应该更改为
@PrimaryKeyJoinColumn(name="ID")
(或者必须将其删除,因为默认是使用与父表中相同的列名)参见 < a href="http://download.oracle.com/javaee/6/api/javax/persistence/PrimaryKeyJoinColumn.html" rel="nofollow">http://download.oracle.com/javaee/6/api/javax/persistence/PrimaryKeyJoinColumn.html。
The
EMPLOYEEID
column in manager shouldn't be there.@PrimaryKeyJoinColumn
means that the primary key is also the join column. So, theID
column inMANAGER
is both the primary key and the foreign key toEMPLOYEE
.And the annotation should of course be changed to
@PrimaryKeyJoinColumn(name="ID")
(or it must be removed, since the default is to use the same column name as in the parent table)See http://download.oracle.com/javaee/6/api/javax/persistence/PrimaryKeyJoinColumn.html.