问题描述
我想用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))
列表< 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角色;
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
第一次,当我尝试持续一个用户UserRolesROLE_USER,没问题。插入用户和UserRoles和连接表。
我的问题是当我尝试使用相同的UserRoles来保留第二个用户。
我检查UserRoles是否存在通过查找( userRolesServices.getUserRoleByName(...))。
如果存在 - >将此UserRoles添加到用户列表(id +角色名称),否则我创建一个新的(唯一的角色名称)。
当我尝试保留第二个用户,我获得以下异常:
分离的实体保留:..... UserRoles(可能是因为在另一个事务中执行getUserRoleByName)
如果我不使用 getUserRoleByName (仅* new UserRoles(ROLE_USER); *),我获得以下异常:
... ConstraintViolation:ROLE_NAME的重复条目...
所以,如何正确地使用 @很多很多关系?
对于上述问题,我会说你的实体关系级联错误。考虑这一点:用户可以有多个角色,但系统中可以存在固定数量的角色。所以CASCADE ALL从用户
实体没有任何意义,因为 UserRoles
的生命周期不应该取决于用户
实体生命周期。例如。当我们删除用户
时,不应该删除 UserRoles
。
分离实体持久化异常只会在您传递具有主键已设置为持久化的对象时发生。
删除级联和您的问题将会解决,现在只需要确定你将如何插入用户角色。根据我的说法,应该有单独的功能。
还不要使用 ArrayList
,使用 HashSet的
。 ArrayList
允许重复。
I want to persist my entity with ManyToMany relation. But i have some problem during persisting process.
My entities :
@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
}
and
@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
}
Service code :
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
First time, when I try to persist a User with UserRoles "ROLE_USER", no problem. User and UserRoles and join tables are inserted.
My problem is when I try to persist a second User with the same UserRoles.I check if the UserRoles exists by finding it (userRolesServices.getUserRoleByName(...)).If exists -> add this UserRoles to User list (id + role name) else i create a new one (only role name).
By when I try to persist the second User, i obtain the following exception :"detached entity to persist : .....UserRoles" (maybe because getUserRoleByName is performed in another transaction)
If I do not use getUserRoleByName (only *new UserRoles("ROLE_USER");*), i obtain the following exception :"...ConstraintViolation : Duplicated entry for 'ROLE_NAME' ..."
So, how to properly persist an entity with @ManyToMany relation ?
For above problem I would say your entity relationship cascade is wrong. Consider this: A user can have multiple roles but there can be fixed number of roles that can exist in the system. So CASCADE ALL from User
entity does not make any sense, since life cycle of UserRoles
should not depend on User
entity life cycle. E.g. when we remove User
, UserRoles
should not get removed.
detached entity to persist exception will only occur when you are passing object which has primary key already set to persist.
Remove cascade and your problem will be solved now only thing you will need to decide is how you are going to insert User roles. According to me there should be separate functionality to do so.
Also do not use ArrayList
, use HashSet
. ArrayList
allows duplicates.
这篇关于如何保持@ManyToMany关系 - 重复条目或分离的实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!