java – 如何持久化@ManyToMany关系 – 重复条目或分离实体

我想用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持久保存第二个用户时.
我通过查找UserRolesServices.getUserRoleByName(…)来检查UserRoles是否存在.
如果存在 – >将此UserRoles添加到用户列表(id角色名称),否则我创建一个新的(仅角色名称).

当我尝试持久保存第二个用户时,我获得以下异常:
“分离的实体要坚持:…… UserRoles”(可能是因为getUserRoleByName是在另一个事务中执行的)

如果我不使用getUserRoleByName(仅* new UserRoles(“ROLE_USER”); *),我将获得以下异常:
“… ConstraintViolation:’ROLE_NAME’重复输入……”

那么,如何使用@ManyToMany关系正确地持久化实体呢?

解决方法:

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

只有在传递已将主键设置为持久的对象时,才会发生分离实体持久异常.

删除级联,您的问题现在将解决,您只需要决定如何插入用户角色.据我所知,应该有单独的功能.

也不要使用ArrayList,使用HashSet. ArrayList允许重复.

上一篇:mysql – 在插入之前插入检查重复的语句


下一篇:如何在php数组中允许重复键