gpt4 book ai didi

@MapsId、@EmbeddedId 的 Hibernate 异常

转载 作者:行者123 更新时间:2023-12-02 23:33:42 29 4
gpt4 key购买 nike

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

Caused by: org.hibernate.PropertyAccessException: could not set a field value by reflection setter of com.test.entities.EmployeeId.serverId

但是,让我们从头开始...我有一个实体 Employee 的复合主键,它由其他两个实体(Server >网站)。为了有一个干净的设计,我在 Employee 实体中使用实体关系,这应该反射(reflect)在 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注释应该反射(reflect)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 需要一个 setter,但只是为了确保我已经为 Employee 的每个字段(包括 ID)提供了 setter 、WebsiteServer 实体。正如预期的那样 - 没有任何变化,Hibernate 仍然找不到(已经存在的)setter。

您认为这可能是一些错误,还是我只是不理解 JPA 2.0 合约的某些部分?

提前致谢!

最佳答案

解决方案在这里:遇到了同样的问题,并且现在开始工作

为了让它工作,您的 Employee 类的 EmployeeId 应该在 Employee 的构造函数中实例化,或者在进行持久化之前在 SessionBean 中实例化。

否则,它会尝试将嵌入的 ID 值设置为空。

不确定这是否正常,或者是否是 JPA 规范的错误实现。我认为后者是因为你的 PK 的构造函数已经定义并且 hibernate 应该能够自己调用它。

关于@MapsId、@EmbeddedId 的 Hibernate 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7984356/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com