JPA:父子关系合并不起作用

时间:2019-03-08 08:28:47

标签: java hibernate jpa

我一直在尝试使用JPA / Hibernate建立一个相当简单的父子关系,尽管有很多教程和文章,但我仍然无法使其正常工作。

我有一个带有数字ID的Customer实体,其中包含一个Address实体列表。地址实体具有一个复合密钥,该复合密钥由客户ID上的外键和使其唯一的序列号组成(但仅在客户ID的上下文中)。

我希望能够对Customer实体执行经典的CRUD操作,这也应该反映给Address实体(例如,当我在客户列表中添加,更新或删除地址时)。

@Entity(name = "Customer ")
@Table(name = "customer ")
@DynamicUpdate
public class Customer implements Serializable
{
    @Id
    @Column(name = "id", nullable = false)
    private Long id;

    @OneToMany(mappedBy = "customer", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Address> addresses;

    @Override public boolean equals(Object obj)
    {
        return obj instanceof Customer && ((Customer ) obj).getId() == this.getId();
    }
}

-

@Entity(name = "Address")
@Table(name = "address")
@DynamicUpdate
public class Address implements Serializable
{
    @Id
    @ManyToOne
    @JoinColumn(name = "customer_id", nullable = false)
    private Customer customer;

    @Id
    @Column(name = "seqnumber", nullable = false)
    private Integer seqnumber;

    @Override public boolean equals(Object obj)
    {
        return obj instanceof Address
            && ((Address) obj).getCustomer().equals(this.getCustomer())
            && ((Address) obj).getSeqNumber() == this.getSeqNumber();
    }
}

使用javax.persistence.EntityManager.persist创建客户+地址并使用javax.persistence.EntityManager.find检索客户已经成功。 但是,在调用javax.persistence.EntityManager.merge时,我无法使用新的/更改/删除的地址来更新客户。

// get data from REST service

// create customer entity - a customer with id 123 already exists in the db
Customer c = new Customer();
c.setId(123);

// create new address entity - no address with seqnumber 2 for customer 123 exists in db
Address a = new Address();
a.setCustomer(c); // or setCustomerId(123) when I tried unidirectional without the ManyToOne
a.setSeqNumber(2);
// add address to customer
c.getAddresses().add(a);

entityManager.merge(c);

我尝试了单向的OneToMany关系,该关系具有客户实体中的地址列表,并且仅具有地址实体中具有地址序号的客户ID。但是,当我从列表中删除一个地址并添加一个新地址时,调用merge导致插入到地址表中,并且复合键为null(尽管在合并之前已设置)。

因此,我切换到双向OneToMany / ManyToOne关系,并在Address实体中添加了Customer对象,而不是客户ID(请参见上面的类)。这意味着我不得不在Address类的equals方法中使用customer对象而不是customer-id,这导致了StackOverflowError。

有人可以给我提示如何正确建模吗?我需要对关系进行建模吗?调用合并不是正确的方法吗?

感谢您的帮助,在此先感谢您!


更新: 我终于在Hibernate论坛here上找到了答案。似乎合并功能不能(始终)保证我要寻找的行为。合并应用于“重新附加已分离的实体,而不用于获取任意临时对象”。 因此,我没有通过合并简单地通过find来获取现有实体,然后更新了所获取的现有实体的地址列表以匹配我的瞬时更新实体。

0 个答案:

没有答案