#spring-boot #spring-data-jpa #spring-data #many-to-many
#spring-boot #spring-data-jpa #spring-данные #многие ко многим
Вопрос:
У меня есть две сущности, одна — пользователь, а другая — роль. Привязка пользователя к роли — это двунаправленное сопоставление manytomany. Я заполнил свою базу данных (postgres) некоторыми предопределенными ролями.
Таблица пользователя выглядит следующим образом
@Entity(name = "user_identity")
public class UserIdentity {
@Column(name = "user_identity_id", nullable = false, unique = true,
updatable = false)
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy =
"org.hibernate.id.UUIDGenerator")
@Id()
@JsonProperty("userIdentityId")
private String userIdentityId = null;
@ManyToMany(targetEntity= Role.class, fetch = FetchType.EAGER, cascade =
{CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(name = "user_identity_roles", joinColumns = {
@JoinColumn(name = "user_id", referencedColumnName =
"user_identity_id") }, inverseJoinColumns = {
@JoinColumn(name = "role_id",
referencedColumnName = "id") })
private List<Role> roles = new ArrayList<Role>();
/**
* Returns the value of '<em><b>roles</b></em>' feature.
*
* <!-- begin-user-doc --> <!-- end-user-doc -->
*
* @return the value of '<em><b>roles</b></em>' feature
*/
public List<Role> getRoles() {
return roles;
}
/**
* Sets the '{@link UserIdentity#getRoles() <em>roles</em>}' feature.
*
* <!-- begin-user-doc --> <!-- end-user-doc -->
*
* @param newRoles the new value of the '{@link UserIdentity#getRoles() roles}'
* feature.
*/
public void addRole(Role newRole) {
this.roles.add(newRole);
newRole.getUsers().add(this);
}
}
Таблица ролей выглядит следующим образом
public class Role{
@Id()
@Column(name = "id", nullable = false, unique = true, updatable =
false)
@GeneratedValue(generator = "UUID")
@GenericGenerator(name = "UUID", strategy ="org.hibernate.id.UUIDGenerator")
private String id = null;
@ManyToMany(mappedBy = "roles",, cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
@JsonIgnore
private List<UserIdentity> users = new ArrayList<UserIdentity>();
public List<UserIdentity> getUsers() {
return users;
}
public void addUsers(UserIdentity newUser) {
this.users.add(newUser);
}
}
При создании пользователя с ролями таблица user_identity_roles (таблица соединений) обновляется идентификатором пользователя и идентификатором роли.
обновление существующего пользователя с новой ролью не работает. ниже приведен код для обновления существующего пользователя с новой ролью.
@Transactional(propagation = Propagation.REQUIRED)
public boolean updateRoleOfUser(String userId, String roleId) {
if (Strings.isNullOrEmpty(roleId) || Strings.isNullOrEmpty(userId)) {
return false;
}
Optional<UserIdentity> existingUser = userRepository.findById(userId);
if (!existingUser.isPresent()) {
throw new ResourceNotFoundException(userId, "User not found with this id");
}
UserIdentity oldUser = existingUser.get();
Optional<Role> roleById = roleRepository.findById(roleId);
if (!roleById.isPresent()) {
throw new ResourceNotFoundException(roleId, "role not found with this id");
}
Role role = roleById.get();
oldUser.getRoles().add(role);
UserIdentity newUserIdentity = userRepository.save(oldUser);
role.getUsers().add(newUserIdentity);
return newUserIdentity != null;
}
Я уже пытался использовать Set вместо List.
Я использую JpaRepository spring data.
Моим ожидаемым результатом было бы сохранение новых идентификаторов ролей в сгенерированной таблице соединений. Было бы очень полезно получить некоторые указания по этому вопросу
Ответ №1:
Вы должны выполнить двунаправленное сопоставление перед сохранением. Роль должна быть добавлена к пользователю, а пользователь должен быть добавлен к роли. После этого может быть запущено сохранение. На данный момент вы добавляете роль пользователю, сохраняете, а затем добавляете пользователя к роли.
Редактировать: Или используйте уже определенный метод oldUser.addRole(роль), который уже выполняет двунаправленное отображение.