Java JPA:父子关系合并不工作

Java JPA:父子关系合并不工作,java,hibernate,jpa,Java,Hibernate,Jpa,我一直试图用JPA/Hibernate建立一个相当简单的亲子关系模型,尽管有大量的教程和帖子,我还是没能让它发挥作用 我有一个带有数字ID的客户实体,它有一个地址实体列表。地址实体有一个复合密钥,由客户ID上的外键和序列号组成,以使其唯一(但仅在客户ID的上下文中) 我希望能够在客户实体上执行经典的CRUD操作,这也应该反映在地址实体上(当我在客户列表中添加、更新或删除地址时) 使用javax.persistence.EntityManager.persistent创建客户+地址,并使用java

我一直试图用JPA/Hibernate建立一个相当简单的亲子关系模型,尽管有大量的教程和帖子,我还是没能让它发挥作用

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

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

使用javax.persistence.EntityManager.persistent创建客户+地址,并使用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对象,而不是Customer id(参见上面的类)。这意味着我必须在Address类的equals方法中使用customer对象而不是customer id,这导致了StackOverflower错误

有人能给我一个关于如何正确建模的提示吗?我是否需要以不同的方式对关系进行建模?调用merge不是正确的方法吗

感谢您的帮助,提前谢谢


更新: 我终于在Hibernate论坛上找到了答案。似乎merge函数不能(总是)保证我所寻找的行为。合并应用于“重新连接分离的实体,而不是获取任意瞬态对象”。 因此,我不是合并,而是通过find获取现有实体,然后更新获取的现有实体的地址列表,以匹配临时更新的实体

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