Reputation: 4486
I have a @ManyToMany relationship between two entities. When I perform an update on the owning side, it appears that JPA deletes all the linked records from my database and re-inserts them. For me this is a problem because I have a MySQL trigger that fires before a record is deleted. Any ideas on how to get around this problem?
@Entity
public class User {
@Id
@Column(name="username")
private String username;
...
@ManyToMany
@JoinTable(name="groups", joinColumns=
@JoinColumn(name="username", referencedColumnName="username"),
inverseJoinColumns=@JoinColumn(name="groupname",
referencedColumnName="type_id"))
private List<UserType> types;
...
}
@Entity
public class UserType {
@Id
@Column(name="type_id")
private String id;
@ManyToMany(mappedBy="types")
private List<User> users;
...
}
Upvotes: 3
Views: 13003
Reputation: 966
Use Set
instead of List
solved the problem. But I have no idea why it works.
Another solution provided by Hibernate is to split the @ManyToMany
association into two bidirectional @OneTo@Many
relationships. See Hibernate 5.2 documentation for example.
If a bidirectional
@OneToMany
association performs better when removing or changing the order of child elements, the@ManyToMany
relationship cannot benefit from such an optimization because the foreign key side is not in control. To overcome this limitation, the link table must be directly exposed and the@ManyToMany
association split into two bidirectional@OneToMany
relationships.
Upvotes: 3
Reputation: 15368
Try this one:
1) change declaration to:
private List<UserType> types = new Vector<UserType>();
2) never call
user.setTypes(newTypesList)
3) only call
user.getTypes().add(...);
user.getTypes().remove(...);
Upvotes: 2
Reputation: 29240
Its probably related to this question. You have to ensure you have an appropriately defined hashCode an equals method in your mapped object so that Eclipselink can determine equality and thus determine that the existing objects map to existing objects in the DB. Otherwise it has no choice but to recreate the child objects every time.
Alternatively, I've read that this kind of join can only support efficient adding and removing of list items if you use an index column, but that's going to be EclipseLink specific, since the JPA annotations don't seem to support such a thing. I know there is an equivalent Hibernate annotation, but I don't know what it would be in Eclipselink, if such a thing exists.
Upvotes: 1