Java JPA多对多关系:无法使用活动关系删除子实体

Java JPA多对多关系:无法使用活动关系删除子实体,java,hibernate,jpa,Java,Hibernate,Jpa,在数据库中,我有用户和角色实体。作为角色实体共享多对多关系可以分配给多个用户实体,另一方面,用户实体可以分配给多个角色实体 我的实体类如下所示 UserEntity @Entity public class UserEntity implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; @Column(unique = true,

在数据库中,我有
用户
角色
实体。作为
角色
实体共享多对多关系可以分配给多个
用户
实体,另一方面,
用户
实体可以分配给多个
角色
实体

我的实体类如下所示

UserEntity

@Entity
public class UserEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    @Column(unique = true, nullable = false)
    private String username;
    @ManyToMany
    private Set<RoleEntity> roles;

    ...
}
@Entity
public class RoleEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    @Column(unique = true, nullable = false)
    private String name;
    @ManyToMany(mappedBy = "roles")
    private Set<UserEntity> users;

    ...
}
@实体
公共类UserEntity实现可序列化{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私人长id;
@列(unique=true,nullable=false)
私有字符串用户名;
@许多
私人设定角色;
...
}
角色属性

@Entity
public class UserEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    @Column(unique = true, nullable = false)
    private String username;
    @ManyToMany
    private Set<RoleEntity> roles;

    ...
}
@Entity
public class RoleEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    @Column(unique = true, nullable = false)
    private String name;
    @ManyToMany(mappedBy = "roles")
    private Set<UserEntity> users;

    ...
}
@实体
公共类RoleEntity实现可序列化{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私人长id;
@列(unique=true,nullable=false)
私有字符串名称;
@许多(mappedBy=“角色”)
私人用户;
...
}
通过这种配置,我能够将实体相互映射。我还可以删除
用户
实体。但只要关系存在,我就不能删除
角色
实体

如果我添加
cascade=CascadeType.REMOVE
则会删除
角色
,当然也会删除
用户


当前要使此工作正常,唯一的方法是在两侧定义一个
@JoinTable
。但这似乎更像是一种解决办法。我做错了什么?由于这是一个常规用例,因此必须有解决方案,尽管我还没有找到它…

您需要连接表,但它不是一个解决方案。请记住,您正在将面向对象模型映射到关系模型。在关系模型中表达多对多关系的唯一方法是定义@JoinTable

更新:在答案中添加注释
您应该仅在一个实体中定义
@JoinTable
,例如
用户实体
角色实体
中的
mappedBy=“roles”
继承了
@jointcolumn
@JoinTable
名称的定义

然后,您需要定义要在关系的两侧执行的级联操作

RoleEntity

@ManyToMany(mappedBy = "roles")
private Set<UserEntity> users;
@ManyToMany
@JoinTable(...)
private Set<RoleEntity> roles;

我不喜欢这种方法的是,我会有双重定义。我刚才看到的另一件事是
@PreRemove
标记。我将一个
PreRemove
方法添加到
角色
实体中,在该实体中,我将角色从其所有
用户
中移除,它也可以工作。
@JoinTable
的好处是,它看起来更光滑,而且我没有任何双重定义。你说的双重定义是什么意思
mappedBy
旨在继承其他实体中的关系定义。很抱歉,我的错误。我们目前有一个自定义的
@JoinTable
命名,当然需要在两侧声明。为什么??您应该只在一个实体中定义
@JoinTable
,例如
UserEntity
roleseentity中的
mappedBy=“roles”
继承了
@jointcolumn
和@JoinTable名称的定义。等等,这样我又得到了约束异常,当我尝试删除与
用户有关系的
角色
时,是否检查了映射在数据库中的外观?如果我没记错的话,如果不添加@JoinTable,数据库中实际发生的是两个连接表,hibernate以某种方式管理它们。这可能会给你带来一些问题。我不知道这两张桌子。JPA规范确实规定了只有一个表: