Hibernate异常与@MapsId,@EmbeddedId [英] Hibernate exception with @MapsId, @EmbeddedId

查看:112
本文介绍了Hibernate异常与@MapsId,@EmbeddedId的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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


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

但是,让我们从头开始...我有一个用于实体 Employee 的复合主键,其中包含外键给另外两个实体( Server 网站)。为了有一个干净的设计,我使用Employee实体中的实体关系,这应该体现在 EmployeeId 嵌入式中。这个例子非常简单,如下所示:

  @Entity 
公共类Server实现Serializable {

@Id
@GeneratedValue
private int id;

私人字符串网址;

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







 @Entity 
public class Website implements Serializable {

@Id
@GeneratedValue
private int id;

私人字符串名称;

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







  @Embeddable 
public class EmployeeId实现Serializable {

protected int websiteId;
保护int serverId;






  @Entity 
public class Employee实现Serializable {

@EmbeddedId
private EmployeeId id;

private String firstName;

@ManyToOne
@MapsId(serverId)
私有服务器服务器;

@OneToOne
@MapsId(websiteId)
私人网站网站;
$ b $ public Employee(){}
$ b public Employee(String firstName,Server server,Website website){
this.firstName = firstName;
this.server = server;
this.website = website;






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

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

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

tx.begin();

服务器s =新服务器(BigServer);
em.persist(s);

网站w =新网站(domain.com);
em.persist(w);

员工e =新员工(John,s,w);
em.persist(e);

tx.commit();

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

$ / code>

正如你所看到的,我在这里没有做任何奇特的东西 - 只是在 Employee 对象中设置实体并保存它。据我所知, @MapsId 注解应该反映 EmbeddedId 中带注释的实体的状态。



现在的问题是,在EclipseLink中一切正常,实体正常保持。当我将JPA 2.0提供程序更改为Hibernate(4.0 CR5)时,它将引发 PropertyAccessException


线程mainjavax.persistence.PersistenceException:
org.hibernate.PropertyAccessException:无法设置字段值
com.test.entities.EmployeeId.serverId的反射设置程序在
org。 hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1353)
。在
org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1281)在
组织
。 hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1287)维持在com.test.Standalone
org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:853)


中的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)
at
org。 hibernate.mapping.Component $ ValueGenerationPlan.execute(Component.java:436)
。在
org.hibernate.id.CompositeNestedGeneratedValueGenerator.generate(CompositeNestedGeneratedValueGenerator.java:121)
。在
org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:120)
。在
org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:78)
。在
org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:180)
。在
org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:136)
at
org.hibernate.event.internal.DefaultPersistEventListener.onPersis t(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)在显示java.lang.NullPointerException
sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:36)
。在
sun.reflect.UnsafeIntegerFieldAccessorImpl:
... 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 more


我不知道NullPointerException可能来自哪里 - 可以看到设置了所有的实体属性。



我甚至不知道为什么Hibernate需要一个setter ,但是为了确保我为每个字段(包括ID)提供了setter( Employee ), code>,网站服务器实体。正如所料 - 没有什么变化,Hibernate仍然无法找到(已经存在的)setter。



你认为这可能是一些错误,或者我只是不明白某些部分JPA 2.0合约?



预先感谢!

解决方案

一个href =https://issues.jboss.org/browse/JBPAPP-6475 =nofollow>这个问题。它只是表明如果实体
包含以下条件,则可能抛出


org.hibernate.PropertyAccessException:


  1. 使用@EmbeddedId

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


正如您所看到的,到目前为止建议的唯一解决方法是不要使用@EmbeddedId ,这很奇怪。


I've got a problem with @MapsId annotation and @EmbeddedId. When running a code in Hibernate I get:

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

But, let's start from the beginning... I have a composite primary key for entity Employee which consists of foreign keys to two other entities (Server and Website). In order to have a clean design I use entity relationships in Employee entity which should be reflected in the EmployeeId embeddable. The example is quite simple and is as follows:

@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;
    }
}

Now I have some simple test method written in Java SE (note this is a regular class executed from static main method - it is not a JUnit class):

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();
}

As you can see, I'm not doing any fancy stuff here - just set entities in the Employee object and persist it. As I understand, the @MapsId annotation should reflect the state of the annotated entity in the EmbeddedId.

Now the problem is that in EclipseLink everything works smoothly and entities are properly persisted. When I change the JPA 2.0 provider to Hibernate (4.0 CR5) it throws me an 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

I don't know where from the NullPointerException might come from - as you can see all entity properties are set.

I don't even know why on earth Hibernate needs a setter, but just to be sure I've provided setters for every field (includng IDs) for Employee, Website and Server entities. As expected - nothing changed and Hibernate still cannot find (already present) setter.

Do you think it might be some bug or I just didn't understand some part of the JPA 2.0 contract?

Thanks in advance!

解决方案

See this issue. It simply states that

org.hibernate.PropertyAccessException may be thrown if an Entity contains the following conditions:

  1. Uses @EmbeddedId
  2. Uses @JoinTable on a collection or association property/field, which references another property/field of the entity.

As you see, the only 'workaround' suggested so far is Do not use @EmbeddedId, which is kind of weird.

这篇关于Hibernate异常与@MapsId,@EmbeddedId的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆