如何更新具有" orphanRemoval = true"的JPA字段?

时间:2014-06-12 14:20:03

标签: java hibernate jpa orm hibernate-mapping

我正在使用JPA 2.0和Hibernate 4.1.0.Final。我有这个实体(用户和地址对象之间的单向关系)......

@Entity
@Table(name = "user")
public class User implements Serializable
{

    @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL}, orphanRemoval=true)
    @JoinTable(name = "user_address", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "address_id"))
    private Set<Address> addresses;

在我的“updateUser”方法中,我有这段代码

        user.setAddresses(addresses);

调用

public void setAddresses(Set<Address> addresses)
{
    if (this.addresses == null)
    {
        this.addresses = new HashSet<Address>();
    }
    this.addresses.clear();
    if (addresses != null)
    {
        this.addresses.addAll(addresses);
    }   // if
}

问题是地址仅在“地址”是新对象时保存,而不是重新保存现有地址实体。使用现有地址更新用户需要做什么?

编辑:以下是我如何保存实体...

protected Object save(Object obj)
{
    if (obj != null)
    {
        final Object id = getId(obj);
        if (id == null)
        {
            m_entityManager.persist(obj);
        }
        else
        {
            obj = m_entityManager.merge(obj);
        }   // if
    }   // if
    return obj;
} // save

2 个答案:

答案 0 :(得分:2)

为了保存用户和调用session.merge所需的地址:

user.setAddresses(addresses);
session.merge(user);

合并将从User级联到Addresses,它将适用于新实体和分离的实体。

同样清除列表并添加元素也不是很好。我建议做类似的事情:

//always initialize the children ollections
private Set<Address> addresses = new HashSet<Address>();

//make sure equals/hashcode are implemented according to the business key semantics
//don't use the entity id for equals and hashcod

public void setAddresses(Set<Address> addresses) {  
    //1. remove the existing addresses that are not found in the new ones
    this.addresses.retainAll(addresses);
    //2. add the new addresses too, the common ones will be ignored by the Set semantics
    this.addresses.addAll(addresses);
}

答案 1 :(得分:1)

Collection属性的最佳实践是将集合初始化为一个新的空集合,让Hibernate对其进行代理并以正确的方式管理对象删除。
尝试将代码更改为

@GenericGenerator(name = "uuid-strategy", strategy = "org.collegeboard.springboard.core.util.SpringboardUUIDGenerator")
@Entity
@Table(name = "user")
public class User implements Serializable
{

    @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL}, orphanRemoval=true)
    @JoinTable(name = "user_address", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "address_id"))
    private Set<Address> addresses = new HashSet<Address>;

另请查看Hibernate @ManyToOne only works with CascadeType.ALL以获取正确的注释/持久性方法对