子类和超类之间的双向 OneToMany 关联不起作用(JPA 与 Hibernate 3.6.7)

发布于 2024-12-12 18:39:59 字数 3838 浏览 6 评论 0原文

我有两个类,员工和经理。 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

静若繁花 2024-12-19 18:39:59

管理器中的 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, the ID column in MANAGER is both the primary key and the foreign key to EMPLOYEE.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文