Проблема с обновлением коллекций после перехода на Spring boot 3.0 и Java 17.
у меня действительно странная проблема с сохранением существующего пользователя в базе данных**, и эта ошибка не реплицируется для каждой записи**, и это то, чего я обычно не понимаю. У меня есть пользовательская сущность с таблицей карт user_roles с двумя полями user_id и role_id, которые находятся в собственном ключе этой таблицы (users_roles).
**До перехода на Java 17 и Spring Boot 3.0 (с Java 11 и Spring Boot 2.7) эта проблема не возникала **но после сохранения пользователя, который сопоставляет новый набор ролей (который равен старому набору ролей, метод равен( ) возвращает true в этом случае) у меня проблема с тем, что Spring пытается вставить дублированную запись в таблицу user_roles, и это вызывает ошибку «JdbcSQLIntegrityConstraintViolationException, нарушение уникального индекса или первичного ключа»
@Getter
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "users")
public class User implements UserDetails {
@Id
private int id;
@Column(nullable = false, unique = true, length = 100)
private String login;
@Column(nullable = false, length = 100)
@ToString.Exclude
private String password;
@Column(nullable = false, name = "is_active")
private boolean active;
private LocalDateTime validFrom;
private LocalDateTime validTo;
@ManyToMany(fetch = FetchType.EAGER,cascade = {CascadeType.PERSIST,CascadeType.MERGE})
@JoinTable(
name = "users_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles;
@UpdateTimestamp
private LocalDateTime lastModifiedAt;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private UserState state;
}
я пытался переопределить метод равенства и хэш-код, это не помогло (даже пытался дать просто вернуть true, как для роли, так и для пользователя), пытался изменить типы каскада и не знаю случая ошибки
** если новая сущность, которая будет сохранена, будет иметь набор ролей СТАРЫЙ ПОЛЬЗОВАТЕЛЬ, как в этом примере ниже, ошибка не возникнет ** ошибка произойдет, только если строка.roles(userByLogin.get().getId())
здесь нет (значит, применяются новые-старые роли)
//userConvertedFromHttpRequest - by the name user is created from payload from http request but, set of roles assigned to him is created by seraching roles in DB,
@Transactional
default User persistByExternalUserId(User userConvertedFromHttpRequest ) {
final Optional<User> userByLogin = findByLogin(userConvertedFromHttpRequest.getLogin());
if (userByLogin.isPresent()) {
User userToSave = user;
userToSave = userToSave.toBuilder()
.id(userByLogin.get().getId())
.roles(userByLogin.get().getRoles())
.build();
return save(userToSave);
} else {
return save(userConvertedFromHttpRequest);
}
}