i have a really strange problem with saving existing user in database,** and this errror isn't replicable to every record**, and that is what i mostly don't undrestand. I have user Entity with maps table users_roles with have 2 fields user_id and role_id which is on its own key of this table (users_roles).
**Before moving to java 17 and spring boot 3.0 (from java 11 and spring boot 2.7)this problem didnt occured **but after when saving user that maps new Set of roles (which is equal to old set of roles, method equals() returns true in that case) i have problem that spring trying to insert duplicated record to table users_roles and that causes error "JdbcSQLIntegrityConstraintViolationException, Unique index or primary key violation"
@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;
}
i tried to override method equals and hashcode, that didnt help (even tried to give just return true, on Both entites Role and User), tried to change cascasde types, and dont know the case of the error
** if new Entity that will be saved will have OLD USER set of roles like in this example below error wont occure **
error will occure only if the line .roles(userByLogin.get().getId())
is not here (which means that new-old roles are applyed)
//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);
}
}