hibernate多對多關係操作
hibernate多對多當中,我們常常希望只刪除一方已及對應的關係,但不想刪除另一方,怎麼樣達到呢? (這裡只提刪除)
表user和表role多對多,中間表user_role(userId,roleId),user是主控方,role是從方,
在spring+hibernate的環境下,使用的是Annotation配置
User.java
@ManyToMany(cascade = {CascadeType.MERGE,CascadeType.PERSIST}, fetch = FetchType.EAGER)
@JoinTable(name = "user_role",
joinColumns = { @JoinColumn(name = "userId",referencedColumnName="userId") },
inverseJoinColumns = { @JoinColumn(name = "roleId",referencedColumnName="roleId") })
public Set<Role> getRoles() {
return this.roles;
}
Role.java
@ManyToMany(cascade = {CascadeType.MERGE,CascadeType.PERSIST}, fetch = FetchType.EAGER,
mappedBy = "roles")
public Set<User> getUsers() {
return this.users;
}
測試:主控方User刪除,user會被刪除,user_role的中的關係也會被刪除了,但對應的role不會被刪除
@Test
public void testDelete() {
User user = userDao.findById(8);
userDao.delete(user);
}
測試:從方Role刪除,如果user_role裡面沒有對應的roleId,role可以刪除,user不會被刪除
@Test
public void testDelete() {
Role role = roleDao.findById(26);
roleDao.delete(role);
}
測試:從方Role刪除,如果user_role裡面有對應的roleId和別的userId關聯,role不能被刪除
@Test
public void testDelete() {
Role role = roleDao.findById(26);
roleDao.delete(role);
}
會報錯:org.springframework.dao.DataIntegrityViolationException: Could not execute JDBC batch update; nested exception is org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch
update
Caused by: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
Caused by: java.sql.BatchUpdateException: Cannot delete or update a parent row: a foreign key constraint fails (`hrms`.`user_role`, CONSTRAINT `roleId` FOREIGN KEY (`roleId`) REFERENCES `role` (`roleId`)
ON DELETE NO ACTION ON UPDATE NO ACTION)
解決方案:在資料庫裡更改user_role表結構,就是新增約束,就新增roleId的刪除時進行級聯操作
ALTER TABLE `hrms`.`user_role`
ADD CONSTRAINT `roleId`
FOREIGN KEY (`roleId` )
REFERENCES `hrms`.`role` (`roleId` )
ON DELETE CASCADE;
測試:從方Role刪除,如果user_role裡面有對應的roleId,現在role可以刪除,user_role裡面對應的關係也會被刪除,但對應的user不會被刪除,達到我們想要的效果
@Test
public void testDelete() {
Role role = roleDao.findById(26);
roleDao.delete(role);
}