這是一個關於Hibernate生成的關於在多對多映射下刪除一個關係的問題,而不是「級聯」問題。刪除JPA中多對多關係時的奇怪sql行爲
我使用JPA 2和hibernate作爲它的實現。
我有兩個模型,用戶和角色。一個用戶可以有多個角色,而一個角色可以有很多用戶,所以他們有很多一對多映射:
@Entity
class User{
@Id Long id;
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH)
@JoinTable(name = "user_role", inverseJoinColumns = @JoinColumn(name = "role_id"),
joinColumns = @JoinColumn(name = "user_id"))
private List<Role> roles;
}
@Entity
class Role{
@Id Long id;
@ManyToMany(fetch = FetchType.LAZY,cascade = CascadeType.REFRESH, mappedBy = "roles")
private List<User> users;
}
和映射效果很好,休眠自動創建三個表這種映射
table user
table role
table user_role
現在這裏是問題,我想要的只是從一個用戶刪除一個角色(不刪除用戶或角色,只是一個用戶和一個角色之間的一個關係,意味着只需要從表user_role
刪除一個記錄) 。這裏是我試過的代碼:
public void removeOneRoleFromUser(long userId, long roleId){
User user = userService.getById(userId);
Role role = roleService.getById(roleId);
user.getRoles().remove(role); //here
userService.update(user);
}
當我執行這段代碼的時候,它的作用就是把這個角色從用戶上移除了。但是,當我檢查該冬眠它生成的SQL,這不是我所期待的,Hibernate生成的SQL是:
delete from user_role where user_id = {userId}
insert into user_role values({user_id}, {role_id_not_removed})
...
insert into user_role values({user_id}, {another_role_id_not_removed})
所以從一個用戶刪除一個角色,休眠首先從用戶刪除所有角色,然後將那些不應該被刪除的角色逐個添加回給用戶。
而我想到的是隻是一個SQL語句歸檔:
delete from user_role where user_id = {userId} and role_id = {role_id}
我知道有一些其他的方式,我可以像引入另一個實體UserRoleMapping
其映射表user_role
歸檔此,則直接刪除一個UserRoleMapping實例將從一個用戶中刪除一個角色;但我想知道是否有任何解決方案可以滿足當前解決方案的需求。
隨着您當前的映射,這是它的方式。可能會有一些特定於hibernate的「提示」/ etc來改變這種行爲。但請記住,「過早優化是所有邪惡(tm)的根源」 – esej
這僅僅是一個例子,而不是我們應用程序中的真實情況。在我們的應用程序中,一個模型可能有很多其他模型,因此刪除一個關係時會引發大量的sql語句(可能會有數百個)。 – donnior