我想保持与ManyToMany关系的实体。但是我在坚持过程中遇到了一些问题。

我的实体:

@Entity
@Table(name = "USER")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long userId;

    @Column(name = "NAME", unique = true, nullable = false)
    String userName;

    @Column(name = "FORNAME")
    String userForname;

    @Column(name = "EMAIL")
    String userEmail;

    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(name = "USER_USER_ROLES", joinColumns = @JoinColumn(name = "ID_USER"), inverseJoinColumns = @JoinColumn(name = "ID_ROLE"))
    List<UserRoles> userRoles = new ArrayList<UserRoles>();

    // getter et setter
}


@Entity
@Table(name = "USER_ROLES")
public class UserRoles implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long userRolesId;

    @Column(unique = true, nullable = false, name = "ROLE_NAME")
    String roleName;

    // getter et setter
}

服务代码:
User user = new User();
UserRoles role;
try {
    role = userRolesServices.getUserRoleByName("ROLE_USER"); // find jpql - transaction
} catch (RuntimeException e) {
    LOGGER.debug("No Roles found");
    role = new UserRoles("ROLE_USER"); // create new
}
user.addUserRole(role);
user.setUserName(urlId);
user.setUserForname(fullName);
user.setUserEmail(email);
userServices.createUser(user); // em.persist(user) - transaction

第一次,当我尝试使用UserRoles“ROLE_USER”保留用户时,没有问题。插入User和UserRoles以及联接表。

我的问题是当我尝试使用相同的UserRoles保留第二个User时。
我通过找到UserRoles(userRolesServices.getUserRoleByName(...))检查是否存在。
如果存在->将此UserRoles添加到用户列表(ID +角色名称),否则我创建一个新角色(仅角色名称)。

当我尝试保留第二个用户时,出现以下异常:
“要保留的分离实体:..... UserRoles” (可能是因为getUserRoleByName在另一个事务中执行)

如果我不使用getUserRoleByName(仅* new UserRoles(“ROLE_USER”); *),则将获得以下异常:
“... ConstraintViolation:“ROLE_NAME”的重复条目...”

因此,如何正确保留具有 @ManyToMany 关系的实体?

最佳答案

对于上述问题,我会说您的实体关系级联是错误的。考虑以下几点:用户可以具有多个角色,但是系统中可以存在固定数量的角色。所以来自User实体的CASCADE ALL没有任何意义,因为UserRoles的生命周期不应该取决于User实体的生命周期。例如。当我们删除User时,不应删除UserRoles

分离的实体可以持久保留异​​常仅在传递主键已设置为持久化的对象时发生。

删除级联,您的问题现在将得到解决,您只需决定如何插入用户角色即可。据我说,应该有单独的功能。

也不要使用ArrayList,请使用HashSetArrayList允许重复。

10-08 13:02