Проблема, кажется, здесь:
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "users_role", joinColumns = @JoinColumn(name = "users_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;
В частности, CascadeType.ALL
означает, что при попытке удалить User
это удаление будет каскадно соответствовать ролям User
. Весьма маловероятно, что вы захотите, чтобы весь смысл установления отношений «многие ко многим», а не «один ко многим», заключался в том, что нескольким пользователям может быть присвоена определенная роль. Если вы попытаетесь удалить роль (напрямую или через каскадное удаление), то есть две альтернативы:
- удаление распространяется на всех других пользователей, имеющих ту же роль (а затем обратно на все эти роли пользователей, и т. Д. ., Или
- удаление не удалось.
Вы видите (2). Конкретное сообщение о нарушении ограничения связано с строками других пользователей в таблице user_role
при попытке удалить роли.
Мне неясно, действительно ли вы хотите каскадно любых операций персистентности от User
с до назначенных им Role
с. Я склонен не думать, в этом случае вам вообще не нужно указывать атрибут cascade
вашего ManyToMany
:
@ManyToMany
@JoinTable(name = "users_role", joinColumns = @JoinColumn(name = "users_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;
Однако, если вы делаете каскад, вам нужно указать отдельные типы каскадов, которые вы хотите, пропуская CascadeType.REMOVE
, возможно, что-то вроде
@ManyToMany(cascade = {CascadeType.DETACH, CascadeType.REFRESH})
@JoinTable(name = "users_role", joinColumns = @JoinColumn(name = "users_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;