Reputation: 19160
I’m using JPA 2.0 with Hibernate 4.1.0.Final. I have this entity (uni-directional relationship between User and Address objects) …
@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;
In my “updateUser” method, I’m have this code
user.setAddresses(addresses);
which calls
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
}
The problem is the addresses only save if the “addresses” are new objects, as opposed to re-saving existing Address entities. What do I need to do to update my user with existing addresses?
Edit: Here's how I save the entity ...
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
Upvotes: 0
Views: 3356
Reputation: 153810
In order to save both the user and the addresses you need to call session.merge:
user.setAddresses(addresses);
session.merge(user);
The merge will be cascaded from User to Addresses, and it will work for both new Entities as for detached ones.
Also clearing the list and adding the elements back doesn't perform very well. i would recommend doing something like:
//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);
}
Upvotes: 2
Reputation: 18403
Best pratice for Collection properties is to init collection to a new empty collection to let Hibernate proxify it and manage object removal in the right way.
Try change you code as
@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>;
Also look at Hibernate @ManyToOne only works with CascadeType.ALL for correct annotation/persistace methods pairs
Upvotes: 1