You don't need any cascade for this to happen. The contents of the join table for a given user is determined by the contents of the teamList
collection of this user. So if you call saveOrUpdate()
with a User that has an empty team list, Hibernate will remove the contents of the join table for this user.
Hibernate deletes record from many-to-many association table after updating
Question
In my teamwork oriented app I have many-to-many relationship between User and Team, so hibernate creates association table. Problem is, that after updating the User which has Team, hibernate deletes corresponding association record from USER_TEAM table.
User entity:
@Entity
@Table(name="USERS")
public class User extends SelectItem {
@Id
@Column(name="EMAIL")
private String email;
@Column(name="PASSWORD")
private String password;
@Column(name="NAME")
private String name;
@Column(name="GROUPNAME")
private String group;
@ManyToMany(
targetEntity=Team.class
)
@ForeignKey(name="FK_TEAM_TO_USER", inverseName = "FK_USER_TO_TEAM")
@JoinTable(
name="USER_TEAM",
joinColumns=@JoinColumn(name="EMAIL"),
inverseJoinColumns=@JoinColumn(name="TEAMNAME")
)
@LazyCollection(LazyCollectionOption.FALSE)
private List<Team> teamList;
@OneToMany(
fetch = FetchType.EAGER,
mappedBy="user")
private List<Invitation> invitationList;
//getters setters
Team entity:
@Entity
@Table(name="TEAM")
public class Team extends SelectItem {
@Id
@Column(name="TEAMNAME")
private String name;
@ManyToOne
@ForeignKey(name="FK_TEAM_TO_TEAMLEADER")
@JoinColumn(name="TEAMLEADER")
private User teamLeader;
@ManyToMany(
mappedBy = "teamList",
targetEntity = User.class
)
@LazyCollection(LazyCollectionOption.FALSE)
private List<User> memberList;
//getters setters
Here is the log:
INFO: 20.11.2012 22:50:00,170 DEBUG org.hibernate.transaction.JDBCTransaction.begin: begin
INFO: 20.11.2012 22:50:00,175 DEBUG org.hibernate.transaction.JDBCTransaction.begin: current autocommit status: true
INFO: 20.11.2012 22:50:00,175 DEBUG org.hibernate.transaction.JDBCTransaction.begin: disabling autocommit
INFO: 20.11.2012 22:50:00,175 DEBUG hibernate.jdbc.util.SQLStatementLogger.logStatement: select user_.EMAIL, user_.GROUPNAME as GROUPNAME0_, user_.NAME as NAME0_, user_.PASSWORD as PASSWORD0_ from USERS user_ where user_.EMAIL=?
INFO: Hibernate: select user_.EMAIL, user_.GROUPNAME as GROUPNAME0_, user_.NAME as NAME0_, user_.PASSWORD as PASSWORD0_ from USERS user_ where user_.EMAIL=?
INFO: 20.11.2012 22:50:00,176 TRACE type.descriptor.sql.BasicBinder.bind: binding parameter [1] as [VARCHAR] - a@b.com
INFO: 20.11.2012 22:50:00,177 TRACE type.descriptor.sql.BasicExtractor.extract: found [users] as column [GROUPNAME0_]
INFO: 20.11.2012 22:50:00,178 TRACE type.descriptor.sql.BasicExtractor.extract: found [default] as column [NAME0_]
INFO: 20.11.2012 22:50:00,178 TRACE type.descriptor.sql.BasicExtractor.extract: found [default] as column [PASSWORD0_]
INFO: 20.11.2012 22:50:00,251 DEBUG org.hibernate.transaction.JDBCTransaction.commit: commit
INFO: 20.11.2012 22:50:00,252 DEBUG hibernate.jdbc.util.SQLStatementLogger.logStatement: update USERS set GROUPNAME=?, NAME=?, PASSWORD=? where EMAIL=?
INFO: Hibernate: update USERS set GROUPNAME=?, NAME=?, PASSWORD=? where EMAIL=?
INFO: 20.11.2012 22:50:00,260 TRACE type.descriptor.sql.BasicBinder.bind: binding parameter [1] as [VARCHAR] - users
INFO: 20.11.2012 22:50:00,261 TRACE type.descriptor.sql.BasicBinder.bind: binding parameter [2] as [VARCHAR] - andy
INFO: 20.11.2012 22:50:00,261 TRACE type.descriptor.sql.BasicBinder.bind: binding parameter [3] as [VARCHAR] - break
INFO: 20.11.2012 22:50:00,262 TRACE type.descriptor.sql.BasicBinder.bind: binding parameter [4] as [VARCHAR] - a@b.com
INFO: 20.11.2012 22:50:00,264 DEBUG hibernate.jdbc.util.SQLStatementLogger.logStatement: delete from USER_TEAM where EMAIL=?
INFO: Hibernate: delete from USER_TEAM where EMAIL=?
INFO: 20.11.2012 22:50:00,271 TRACE type.descriptor.sql.BasicBinder.bind: binding parameter [1] as [VARCHAR] - a@b.com
INFO: 20.11.2012 22:50:00,274 DEBUG
org.hibernate.transaction.JDBCTransaction.toggleAutoCommit: re-enabling autocommit INFO: 20.11.2012 22:50:00,274 DEBUG org.hibernate.transaction.JDBCTransaction.commit: committed JDBC Connection
The update operation is provided by spring's hibernateTemplate in this simple method in UserDAO:
public void saveUser(User user){
hibernateTemplate.saveOrUpdate(user);
}
(I know that hibernateTemplate shouldn't be used, but I think that's not the point in this problem)
And DAO method is simply called in transaction by spring service bean UserServiceImpl:
@Transactional(readOnly=false)
public void saveUser(User user){
userDao.saveUser(user);
}
As you can see, I don't have any cascade annotations and in update I don't change PK of User (EMAIL) of course, so I don't understand this behaviour. I'm using spring 3.1.0.RELEASE and hibernate 3.6.10.Final.
Thanks for any suggestions or explanations.
La solution