删除第一个实体及其关系而不删除第二个实体 - Spring Data JPA

Remove the first entity and its relationship without removing the second entity - Spring Data JPA

我有两个实体,一个是UserEntity,另一个是RoleEntity,用户可以有多个角色,角色可以被多个用户使用,我的实体看起来像:

@Entity
public class UsersEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(nullable = false)
    private Long id;
    //...
    @ManyToMany(mappedBy = "users")
    private Set<RolesEntity> roles;
    //...

    // Getters and setters
}

@Entity
public class RolesEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(nullable = false)
    private Integer id;
    @NotNull
    @Enumerated(EnumType.STRING)
    @Column(length = 20)
    private RoleEnum name;
    @JoinTable(name = "user_roles", joinColumns = {
        @JoinColumn(name = "role_id", referencedColumnName = "id", nullable = false)}, inverseJoinColumns = {
        @JoinColumn(name = "user_id", referencedColumnName = "id", nullable = false)})
    @ManyToMany
    private List<UsersEntity> users;
}

通常角色是固定的,不会有太大变化。现在我有一个服务:

public void removeUser(Long id) {
    if (userRepository.findById(id).isPresent()) {
        userRepository.deleteById(id);
    } else {
        throw new IllegalArgumentException("User not found!");
    }
}

我的要求是只删除用户,不删除与该用户相关的角色,即删除用户和关系。当我调用我得到的预览方法时。

org.postgresql.util.PSQLException: ERROR: update or delete on table "users" violates foreign key constraint "constraint_user_id" on table "user_roles"
  Detail: Key (id)=(4) is still referenced from table "user_roles".

请问有什么技巧可以解决吗?

您需要将对 UsersEntity 的所有引用设为空。

所以基本上是什么问题?虽然 RolesEntity 引用了 UsersEntity class,但您不能删除它。最简单的事情是为 UsersEntity class 中的每个 RolesEntity 创建一个循环并从中删除所有内容。

然后您就可以从您的数据库中成功删除该用户了。

查看此以获取更多信息:How to remove entity with ManyToMany relationship in JPA (and corresponding join table rows)?

我这样解决了我的问题,我不确定这是否是解决此问题的最佳方法:

public void removeUser(Long id) {
    Optional<UsersEntity> userById = usersRepository.findById(id);
    if (userById.isPresent()) {
        UsersEntity user = userById.get();
        for (RolesEntity role : user.getRoles()) {
            role.setUsers(null);
            rolesRepository.save(role);
        }
        usersRepository.delete(user);
    } else {
        throw new IllegalArgumentException("User not found!");
    }
}

我想你可以使用 CascadeType.REMOVE

    @ManyToMany(cascade = CascadeType.REMOVE, fetch = FetchType.EAGER)
    @JoinTable(
            name = "users_roles",
            joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "role_id"))
    private List<Role> roles;