小编典典

@ MapsId,@ EmbeddedId的休眠异常

hibernate

我在@MapsId注释和上遇到了问题@EmbeddedId。在Hibernate中运行代码时,我得到:

引起原因:org.hibernate.PropertyAccessException:无法通过com.test.entities.EmployeeId.serverId的反射设置器设置字段值

但是,让我们从头开始…我有一个实体的复合主键,Employee它由指向其他两个实体(ServerWebsite)的外键组成。为了设计简洁,我在Employee实体中使用实体关系,该关系应反映在EmployeeId可嵌入对象中。该示例非常简单,如下所示:

@Entity
public class Server implements Serializable {

    @Id
    @GeneratedValue
    private int id;

    private String url;

    public Server() {}

    public Server(String name) {
        this.url = name;
    }
}

@Entity
public class Website implements Serializable {

    @Id
    @GeneratedValue
    private int id;

    private String name;

    public Website() {}

    public Website(String name) {
        this.name = name;
    }
}

@Embeddable
public class EmployeeId implements Serializable {

    protected int websiteId;
    protected int serverId;
}

@Entity
public class Employee implements Serializable {

    @EmbeddedId
    private EmployeeId id;

    private String firstName;

    @ManyToOne
    @MapsId("serverId")
    private Server server;

    @OneToOne
    @MapsId("websiteId")
    private Website website;

    public Employee() {}

    public Employee(String firstName, Server server, Website website) {
        this.firstName = firstName;
        this.server = server;
        this.website = website;
    }
}

现在,我有一些用Java SE编写的简单测试方法(请注意,这是从静态main方法执行的常规类-它 不是 JUnit类):

private void executeTest() {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("standaloneTests");

    EntityManager em = emf.createEntityManager();
    EntityTransaction tx = em.getTransaction();

    tx.begin();

    Server s = new Server("BigServer");
    em.persist(s);

    Website w = new Website("domain.com");
    em.persist(w);

    Employee e = new Employee("John", s, w);
    em.persist(e);

    tx.commit();

    em.close();
    emf.close();
}

如您所见,我在这里没有做任何花哨的事情-
只需在Employee对象中设置实体并将其持久化即可。据我了解,@MapsId注释应反映中带注释的实体的状态EmbeddedId

现在的问题是,在EclipseLink中,一切都可以顺利进行,并且实体可以正确保留。当我将JPA 2.0提供程序更改为Hibernate(4.0
CR5)时,它抛出了 PropertyAccessException

Exception in thread “main” javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: could not set a field value by reflection setter of com.test.entities.EmployeeId.serverId at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1353) at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1281) at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1287) at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:853) at com.test.Standalone.executeTest(Standalone.java:101) at com.test.Standalone.main(Standalone.java:35) Caused by: org.hibernate.PropertyAccessException: could not set a field value by reflection setter of com.test.entities.EmployeeId.serverId at org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:150) at org.hibernate.mapping.Component$ValueGenerationPlan.execute(Component.java:436) at org.hibernate.id.CompositeNestedGeneratedValueGenerator.generate(CompositeNestedGeneratedValueGenerator.java:121) at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:120) at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:78) at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:180) at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:136) at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:64) at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:729) at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:705) at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:709) at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:847) … 2 more Caused by: java.lang.NullPointerException at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:36) at sun.reflect.UnsafeIntegerFieldAccessorImpl.set(UnsafeIntegerFieldAccessorImpl.java:57) at java.lang.reflect.Field.set(Field.java:657) at org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:138) … 13 more

我不知道NullPointerException可能来自哪里-如您所见,所有实体属性都已设置。

我甚至不知道 为什么地球上Hibernate需要一个二传手 ,但只是要肯定我提供制定者,每场(includng的ID)
EmployeeWebsiteServer实体。如预期的那样-没有任何变化,并且Hibernate仍然找不到(已经存在)setter。

您是否认为这可能是某个错误,或者我只是不理解JPA 2.0合同的某些部分?

提前致谢!


阅读 320

收藏
2020-06-20

共1个答案

小编典典

看到这个问题。它只是说

如果实体包含以下条件,则可能引发org.hibernate.PropertyAccessException:

  1. 使用@EmbeddedId
  2. 在集合或关联属性/字段上使用@JoinTable,该属性或字段引用实体的另一个属性/字段。

如您所见,到目前为止Do not use @EmbeddedId,建议的唯一“解决方法”是,这很奇怪。

2020-06-20