Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在JPA中删除多对多关系时出现奇怪的sql行为_Java_Hibernate_Jpa 2.0 - Fatal编程技术网

Java 在JPA中删除多对多关系时出现奇怪的sql行为

Java 在JPA中删除多对多关系时出现奇怪的sql行为,java,hibernate,jpa-2.0,Java,Hibernate,Jpa 2.0,这是一个关于Hibernate生成的sql的问题,关于在多对多映射下删除一个关系,而不是“级联”问题 我使用JPA2和hibernate作为它的实现 我有两个模型,用户和角色。一个用户可以有多个角色,一个角色可以有多个用户,因此他们是多对多映射: @Entity class User{ @Id Long id; @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH) @JoinTable(na

这是一个关于Hibernate生成的sql的问题,关于在多对多映射下删除一个关系,而不是“级联”问题

我使用JPA2和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; 
 }
现在问题来了,我想要的只是从一个用户中删除一个角色(不是删除一个用户或角色,一个用户和一个角色之间只有一个关系,意味着只需要从表
user\u 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);
}
当我执行这段代码时,该角色确实从用户中删除了。但是当我检查hibernate为其生成的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\u role
,然后直接删除一个UserRoleMapping实例将从一个用户中删除一个角色;但是我想知道,有没有什么解决方案可以用当前的解决方案达到预期效果。

我没有检查过这是真的,但它有很多优点

没有任何索引列,列表实际上就是一个包:没有顺序,并且允许重复。因此Hibernate认为在用户的角色列表中可能有两次相同的角色

所以发出
delete from user\u role where user\u id=?而role_id=?
是不可能的,因为它可能会删除多个角色,而不仅仅是从列表中删除的角色


尝试添加索引列,或者使用
集合
而不是
列表

来处理当前映射,这就是方法。可能有一些特定于hibernate的“提示”/etc来更改此行为。但是请记住,“过早优化是万恶之源(tm)”,这只是一个示例,而不是我们应用程序中的真实场景。在我们的应用程序中,一个模型可能有很多其他模型,因此当删除一个关系时会产生很多sql语句(可能有数百个)。切换到“从列表中设置”对我来说很有用,但我宁愿使用列表。联接表的主键已经包括联接外键和反向联接外键,它们是表中仅有的两列,所以我不明白为什么这不起作用。还有别的事吗?
delete from user_role where user_id = {userId} and role_id = {role_id}