java如何持久化@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”持久化一个用户时,没有问题。将插入用户和用户角色以及联接表
我的问题是,当我试图持久化具有相同用户角色的第二个用户时。 我通过查找userRolesServices.getUserRoleByName(…)来检查UserRoles是否存在)。 如果存在->;将此UserRoles添加到用户列表(id+角色名),否则我将创建一个新的(仅角色名)
当我尝试持久化第二个用户时,我获得了以下异常: “要持久化的分离实体:……UserRoles”(可能是因为getUserRoleByName是在另一个事务中执行的)
如果我不使用getUserRoleByName(仅*新用户角色(“角色用户”);*),我获得以下例外: “……约束约束:重复输入‘角色名称’…”
那么,如何正确地保持一个具有@manytomy关系的实体呢
# 1 楼答案
对于上述问题,我认为你们的实体关系是错误的。考虑这一点:用户可以有多个角色,但是系统中可以存在固定数量的角色。因此,从
User
实体级联所有内容没有任何意义,因为UserRoles
的生命周期不应该依赖于User
实体的生命周期。例如,当我们删除User
时,UserRoles
不应该被删除要持久化的分离实体只有在传递主键已设置为持久化的对象时,才会发生异常
移除cascade,您的问题就会得到解决,现在您唯一需要决定的是如何插入用户角色。根据我的说法,这样做应该有单独的功能
也不要使用
ArrayList
,使用HashSet
ArrayList
允许重复# 2 楼答案
如果有人向我和作者提出同样的问题,我会给出我的答案
基本上,我所面临的情况是,当我有一张表时,它是某种常量值。另一个会改变,但它应该映射(
many to many
)到那些常数确切的问题是
USERS
,它是ROLES
Roles
将在系统启动时被知道并添加,因此它们永远不会被删除。即使没有用户会有一些Role
,它也应该仍然在系统中使用JPA的类实现:
用户:
角色:
用法
此设置将轻松地将
Role
添加/删除到User
。只需传递一个数组,f.e.:user.getRoles().add(new Role("ADMIN"));
和merge
的user
删除可用于传递空列表如果在将
Role
添加到用户之前忘记添加它,很可能会出现如下错误:什么和为什么
mappedBy
属性被添加到子实体中,如JPA Docs中所述# 3 楼答案
我也有同样的问题,但还没解决。 我的关系是
Hotel
到DeliveryPartners
。 以下是课程:@Controller类
当我使用合并级联类型时,出现以下异常:
我意识到,在查询部分,没有针对送货表的插入查询,因此可以在hotel_delivery(MTM表)中使用送货。 我现在不知道该怎么办
# 4 楼答案
在同一个事务/实体管理器中执行查询,这似乎是问题所在。否则,请使用find()在当前事务中重新找到它
# 5 楼答案
复制原因:Id是自动生成的,所以每次创建新角色时 使用方法如下:
使用者
角色
控制器(应已将其添加到服务中)
输出
角色
用户角色
如果你喜欢答案,请订阅Youtube Channel Atquil
# 6 楼答案
我得到了同样的错误,但是在添加了cascade=CascadeType之后。所有对于关系双方来说,问题已经解决。 早些时候我是级联型的。ALL仅在关系的父端,在添加子级之后,代码现在运行良好。 这是我的密码
读卡器(父实体):
订阅(子实体):
持久性代码: