我想用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允许重复.