我在@MapsId注释和上遇到了问题@EmbeddedId。在Hibernate中运行代码时,我得到:
@MapsId
@EmbeddedId
引起原因:org.hibernate.PropertyAccessException:无法通过com.test.entities.EmployeeId.serverId的反射设置器设置字段值
但是,让我们从头开始…我有一个实体的复合主键,Employee它由指向其他两个实体(Server和Website)的外键组成。为了设计简洁,我在Employee实体中使用实体关系,该关系应反映在EmployeeId可嵌入对象中。该示例非常简单,如下所示:
Employee
Server
Website
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。
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) Employee,Website和Server实体。如预期的那样-没有任何变化,并且Hibernate仍然找不到(已经存在)setter。
您是否认为这可能是某个错误,或者我只是不理解JPA 2.0合同的某些部分?
提前致谢!
看到这个问题。它只是说
如果实体包含以下条件,则可能引发org.hibernate.PropertyAccessException: 使用@EmbeddedId 在集合或关联属性/字段上使用@JoinTable,该属性或字段引用实体的另一个属性/字段。
如果实体包含以下条件,则可能引发org.hibernate.PropertyAccessException:
如您所见,到目前为止Do not use @EmbeddedId,建议的唯一“解决方法”是,这很奇怪。
Do not use @EmbeddedId