[英]Spring + JPA/Hibernate not saving many-to-many mapping
Situation 情况
I have a RoleEntity
and a UserEntity
. 我有一个
RoleEntity
和一个UserEntity
。 A RoleEntity
contains a list of UserEntity
and vice-versa, resulting in a Many-To-Many
relationship. 一个
RoleEntity
包含一系列UserEntity
,反之亦然,从而导致Many-To-Many
关系。
My UserEntity
: 我的用户
UserEntity
:
public class UserEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(unique = true, nullable = false)
private String username;
@Column(name = "first_name", nullable = false)
private String firstName;
@Column(name = "last_name", nullable = false)
private String lastName;
@Column(nullable = false)
private String email;
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.REFRESH)
@JoinTable(name = "uas_user_role",
joinColumns = @JoinColumn(name = "uas_user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "uas_role_id", referencedColumnName = "id"),
uniqueConstraints = {
@UniqueConstraint(columnNames = {"uas_user_id", "uas_role_id"})}
)
private Set<RoleEntity> roles = new HashSet<>();
...
}
My RoleEntity
: 我的
RoleEntity
:
public class RoleEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(unique = true, nullable = false)
private String name;
@ManyToMany(mappedBy = "roles")
private Set<UserEntity> users;
@ManyToMany
@JoinTable(
name = "uas_role_permission",
joinColumns
= @JoinColumn(name = "uas_role_id", referencedColumnName = "id"),
inverseJoinColumns
= @JoinColumn(name = "uas_permission_id", referencedColumnName = "id"),
uniqueConstraints = {
@UniqueConstraint(columnNames = {"uas_role_id", "uas_permission_id"})}
)
private Set<PermissionEntity> permissions;
...
}
Goal 目标
Now I would like to change the mappings by simply update a single entity. 现在我想通过简单地更新单个实体来更改映射。 For example I want to add a
UserEntity
to a RoleEntity
with id=1: 例如,我想将
UserEntity
添加到id = 1的RoleEntity
:
{
"id": 1,
"name": "Admin_Role",
"users": [{"id": 1}
]
}
Saving this RoleEntity
to it's role repository ( JPARepository.saveAndFlush(Serializable)
), successfully resolves the implied UserEntity
and is returning the updated RoleEntity
将此
RoleEntity
保存到其角色存储库( JPARepository.saveAndFlush(Serializable)
),成功解析隐含的UserEntity
并返回更新的RoleEntity
{
"id": 1,
"name": "Admin_Role",
"users": [{
"id": 1,
"username": "admin",
"firstName": "Administrator",
"lastName": "Administrator",
"email": "info@example.com",
}
]
}
Problem 问题
My test are all passing because I only checked the return value of the save command. 我的测试全部通过,因为我只检查了save命令的返回值。 Now I found out when doing a
roleRepository.findOne(1)
after the persisting, I'll receive the following RoleEntity
: 现在我发现在持久化后执行
roleRepository.findOne(1)
,我将收到以下RoleEntity
:
{
"id": 1,
"name": "Admin_Role",
"users": []
}
The UserEntity
mapping did not get persisted. UserEntity
映射未持久化。 Also when setting spring.jpa.show-sql=true
, I see that only SELECT
operations are executed during the saveAndFlush
command. 同样在设置
spring.jpa.show-sql=true
,我发现在saveAndFlush
命令期间只执行SELECT
操作。 I only want to create mappings with the and don't want to allow editing of the mapping entity, that's why I've disabled any cascading. 我只想创建映射,并且不希望允许编辑映射实体,这就是我禁用任何级联的原因。
I've expected that with this approach, a mapping gets created. 我期望通过这种方法,可以创建映射。 What am I doing wrong?
我究竟做错了什么?
Solution 解
As Amer Qarabsa mentioned: To create a bidirectional mapping, it needs to be set on both sides. 正如Amer Qarabsa所提到的:要创建双向映射,需要在两端进行设置。 Adding one line after saving an entity already does the trick:
保存实体后添加一行已经成功了:
@Transactional
public RoleDto updateRole(RoleDto role) {
RoleEntity roleEntity = roleRepository.findOne(role.getId());
if (roleEntity==null){
throw new ResourceNotFoundException();
}
final RoleEntity savedRoleEntity = roleRepository.saveAndFlush(roleEntity);
savedRoleEntity.getUsers().forEach(user -> user.getRoles().add(savedRoleEntity));
return savedRoleEntity;
}
With the .saveAndFlush(roleEntity)
I'll first update the RoleEntity
and let JPA resolve the UserEntity
. 使用
.saveAndFlush(roleEntity)
我将首先更新RoleEntity
并让JPA解析UserEntity
。 After this, I simply set the RoleEntity
to each UserEntity
of the role. 在此之后,我只需将
RoleEntity
设置为RoleEntity
的每个UserEntity
。 In my case, I don't need to persist that manually, as the transaction will take care of persisting any unsaved changes. 在我的情况下,我不需要手动持久化,因为事务将负责持久保存任何未保存的更改。
那么在双向关系中它不是很简单,你不能把json和它映射到实体这么简单,关系的每一边都应该引用另一边,所以在你的情况下你需要把每个userentity里面角色实体并设置它的角色实体然后保存。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.