我有一个@MapsId
注释和@EmbeddedId
问题。当在Hibernate中运行的代码,我得到:Hibernate例外与@MapsId,@EmbeddedId
产生的原因:org.hibernate.PropertyAccessException:无法设置由 反射二传手一个 字段值com.test.entities.EmployeeId.serverId
但是,让我们从头开始...我有一个实体Employee
的复合主键,它由外键与其他两个实体(Server
和Website
)组成。为了有一个干净的设计,我使用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一些简单的测试方法(注意,这是从静态主要方法执行的常规类 - 它是而不是一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提供商休眠(4.0 CR5),它将引发我一个的PropertyAccessException:螺纹
异常 “主要” javax.persistence.PersistenceException: org.hibernate.PropertyAccessException:无法设置在 org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1353) 在 org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java由com.test.entities.EmployeeId.serverId的 反射设定部字段值:1281) at org.hibernate.ejb.AbstractEntityManagerImpl.convert( AbstractEntityManagerImpl.java:1287) 在 org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:853) 在com.test.Standalone.executeTest(Standalone.java:101)在 com.test.Standalone.main (Standalone.java:35)导致: org.hibernate.PropertyAccessException:无法设置字段值 com.test.entities.EmployeeId.serverId的反射设置器,位于 org.hibernate.property.DirectPropertyAccessor $ DirectSetter.set (DirectPropertyAccessor.java:150) 在 org.hibernate.mapping.Component $ ValueGenerationPlan.execute(Component.java:436) 在 org.hibernate.id.CompositeNestedGeneratedValueGenerator.generate(CompositeNestedGenera tedValueGenerator。的java:121) 在 org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:120) 在 org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:78) 在 有机.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:180) 在 org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:136) 在 org.hibernate.event.internal.DefaultPersistEventListener .onPersist(DefaultPersistEventListener.java:64) at org.hibernate.internal.SessionImpl.firePersist (SessionImpl.java:729) 在org.hibernate.internal.SessionImpl.persist(SessionImpl.java:705) 在org.hibernate.internal.SessionImpl.persist(SessionImpl.java:709) 在 org.hibernate作为。在 sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:36)显示java.lang.NullPointerException 在 sun.reflect.UnsafeIntegerFieldAccessorImpl:ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:847) ... 2更所致.set(UnsafeIntegerFieldAccessorImpl.java:57) at java.lang.reflect.Field.set(Field.java:657)at org.hibernate.property.DirectPropertyAccessor $ DirectSetter.set(DirectPropertyAccessor.java:138) .. 13更多
我不知道NullPointerException可能来自哪里 - 您可以看到所有实体属性都已设置。
我甚至不知道为什么地球上Hibernate需要一个二传手,但只是要确定我为Employee
,Website
和Server
实体提供的制定者,每场(includng的ID)。正如所料 - 没有什么改变,Hibernate仍然无法找到(已经存在的)setter。
您认为这可能是一些错误,或者我只是不理解JPA 2.0合同的某些部分?
在此先感谢!
谢谢@ jFrentic。我发现读“解决方法”确实很奇怪。这就像是说你的汽车里的雨刷坏了,所以解决方法是不使用它们... –
是的,这很伤心,但是因为它被标记为*已知问题*并且仍然具有'打开'状态,所以希望Hibernate团队将在下一个版本中为此做点什么。虽然,我必须承认,我没有试图自己重现你的问题。我认为我看到有人在Hibernate中使用@EmbeddedId,它似乎工作,但我不确定。如果我发现更多,我会回到这里。 – jFrenetic
@jFrentic - 谢谢你。我也看到了一个使用'@ EmbeddedId'的代码,但我认为'@ MapsId'必须弄乱这里的东西。尽管如此,我已经为Hibernate问题添加了一条评论,我会等待他们的回答。 –