我想保持与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
,请使用HashSet
。 ArrayList
允许重复。