【问题标题】:JPA reference other entity in an entity constructorJPA 在实体构造函数中引用其他实体
【发布时间】:2014-08-30 07:57:21
【问题描述】:

在我的数据库表属性中,我将首先加载一个数据列表。每次我想持久化一条MyAttribute的新记录时,我需要先在表Attribute中搜索,然后从表Attribute中选择合适的记录,然后再插入到表MyAttribute中。

@Entity
class MyAttribute{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @ManyToOne(targetEntity = Attribute.class)
    @JoinColumn(name="attribute_id", referencedColumnName="id")
    Attribute detail;

    private String greet;

    public MyAttribute(){
        this.greet = "Hello World.";
        this.detail = new MyDbLayer().selectAttributeDetail("first"); //Error is thrown here.
    }

    //getter & setter
}

@Entity
class Attribute{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Index(name = "name_index")
    @Column(unique=true )
    private String name;

    //getter & setter
}

class MyDbLayer{
    private EntityManagerFactory emf;

    public MyDbLayer() {
        emf = Persistence.createEntityManagerFactory("MyPu");
    }

    public Attribute selectAttributeDetail(String name) {
        EntityManager em = emf.createEntityManager();

        em.getTransaction().begin();

        Query queryGetAttribute = em.createQuery("select a from Attribute a where a.name = :attributeName");

        List<AttributeDescription> attributeDescList = queryGetAttribute.setParameter("attributeName", name).getResultList();

        AttributeDescription tempAttribute = null;

        if (!attributeDescList.isEmpty()) {
            tempAttribute = (AttributeDescription) attributeDescList.get(0);
        }

        em.clear();
        em.close();

        return tempAttribute;
    }
}

我不知道为什么我不断收到如下错误:

javax.persistence.PersistenceException: [PersistenceUnit: MyPu] 无法 构建EntityManagerFactory

原因:org.hibernate.MappingException:无法获取构造函数 对于 org.hibernate.persister.entity.SingleTableEntityPersister

原因:org.hibernate.InstantiationException:无法实例化 测试对象

附:这不是我正在处理的真正代码,但结构或多或少是相同的。

【问题讨论】:

    标签: java jpa


    【解决方案1】:

    为 MyAttribute 创建第二个构造函数怎么样?

    public MyAttribute(){
        this.greet = "Hello World.";
        // this.detail = new MyDbLayer().selectAttributeDetail("first"); //Error is thrown here.
    }
    
    public MyAttribute(Attribute detail){
        this.greet = "Hello World.";
        this.detail = detail;
    }
    

    jpa 也使用默认构造函数来加载持久对象。这可能会导致意外行为

    【讨论】:

    • JPA 需要一个无参数构造函数才能工作,请参阅stackoverflow.com/questions/2808747/…
    • 但是在这种情况下,我不会重写很多调用MyAttribute的代码吗?如果我想减少在调用构造函数的所有不同类中重写它怎么办?
    • 嗯,我认为你必须找到阻力最小的路径。也许创建一个为您构建初始化对象的工厂,然后用工厂调用搜索并替换“new MyAttribute()”
    【解决方案2】:

    JPA 模型中不能从实体访问EntityManager。可以这样做,但是根据实现的不同,它可以有不同的行为。

    在您的情况下,从无参数构造函数访问 EntityManager 绝不是一个好主意。因为那是EntityManager 在加载实体时使用的构造函数。因此,每次MyAttributeEntityManager 加载时,您将尝试创建另一个EntityManager 以初始化detail 关系,该关系将被第一个EntityManager 使用它从数据库加载的值覆盖。

    通常您应该有一个服务层,该服务层可以访问管理您的 JPA 实体的EntityManager

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-08
      • 1970-01-01
      • 2013-08-18
      • 2018-08-08
      • 2019-02-13
      • 1970-01-01
      • 2021-12-21
      相关资源
      最近更新 更多