Aur*_*e77 15 java many-to-many jpa duplicates unique-constraint
我想用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
}
Run Code Online (Sandbox Code Playgroud)
和
@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
}
Run Code Online (Sandbox Code Playgroud)
服务代码:
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
Run Code Online (Sandbox Code Playgroud)
第一次,当我尝试用UserRoles"ROLE_USER"来保持用户时,没问题.将插入User和UserRoles以及联接表.
我的问题是当我尝试使用相同的UserRoles持久保存第二个用户时.我通过查找UserRolesServices.getUserRoleByName (...)来检查UserRoles是否存在.如果存在 - >将此UserRoles添加到用户列表(id +角色名称),否则我创建一个新的(仅角色名称).
当我尝试持久保存第二个用户时,我获得以下异常: "要保留的分离实体:...... UserRoles"(可能因为getUserRoleByName在另一个事务中执行)
如果我不使用getUserRoleByName(仅*new UserRoles("ROLE_USER");*),我将获得以下异常: "... ConstraintViolation:'ROLE_NAME'的重复条目......"
那么,如何使用@ManyToMany关系正确地持久化实体呢?
Ami*_*nde 24
对于上述问题,我会说你的实体关系级联是错误的.请考虑这一点:用户可以拥有多个角色,但系统中可以存在固定数量的角色.所以来自User实体的CASCADE ALL 没有任何意义,因为生命周期不UserRoles应该依赖于User实体生命周期.例如,当我们删除时User,UserRoles不应该删除.
只有在传递已将主键设置为持久的对象时,才会发生分离实体持久异常.
删除级联,您的问题现在将解决,您只需要决定如何插入用户角色.据我所知,应该有单独的功能.
也不要使用ArrayList,使用HashSet.ArrayList允许重复.
如果有人向我和作者提出相同类型的问题,我会提供我的答案.
基本上我面临的是一种情况,当我有一个表是某种CONSTANT值.而另一个会改变,但它应该map(many to many)到那些CONSTANTS.
确切的问题是USERS,它是ROLES.
Roles将被知道并在系统启动时添加,因此它们永远不会被删除.即使没有用户会有一些Role它仍然应该在系统中.
用户:
@Entity
@Table(name = "USERS")
public class User{
@Id
private String login;
private String name;
private String password;
@ManyToMany(cascade = {CascadeType.MERGE})
private Set<Role> roles = new HashSet<>();
Run Code Online (Sandbox Code Playgroud)
作用:
@Entity
@Table(name = "ROLE")
public class Role {
@Id
@Enumerated(value = EnumType.STRING)
private RoleEnum name;
@ManyToMany(mappedBy = "roles")
private Set<User> users = new HashSet<>();
Run Code Online (Sandbox Code Playgroud)
这种设置会很容易地添加/删除Role到User.简单地通过使阵列,FE:user.getRoles().add(new Role("ADMIN"));和merge的user.删除通过传递空列表.
如果您忘记添加Role之前将其添加到用户,则很可能会出现如下错误:
javax.persistence.RollbackException: java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: com.storage.entities.Role@246de37e.
Run Code Online (Sandbox Code Playgroud)
如果选择在两个方向上映射关系,则必须将一个方向定义为所有者,另一个方向必须使用mappedBy属性来定义其映射(...)
cascade = {CascadeType.MERGE}为正确的级联JPA Docs添加级联EntityManager.merge()操作.如果在父项上调用merge(),则子项也将合并.这通常应该用于依赖关系.请注意,这只会影响合并的级联,关系引用本身将始终合并.
| 归档时间: |
|
| 查看次数: |
25190 次 |
| 最近记录: |