#java #sql-server #spring-boot #hibernate #cascade
#java #sql-сервер #весенняя загрузка #спящий режим #каскад
Вопрос:
Я столкнулся с проблемой удаления связанных объектов из моей базы данных. У меня есть торговое приложение, в котором пользователи могут публиковать сделки и выражать свои интересы в сделках других людей.
Когда пользователь удаляет свою учетную запись, все опубликованные сделки и интересы, выраженные этим пользователем, должны быть удалены из базы данных. Однако последнее, похоже, не работает (я также не уверен, работает ли первое, поскольку я не знаю, в каком порядке они выполняются). Я получаю сообщение об ошибке:
Оператор DELETE конфликтовал со ССЫЛОЧНЫМ ограничением «FKq9kr60l7n7h3yf82s44rkoe4g». Конфликт произошел в базе данных «dbi438161_i438161», таблица «dbo.interests», столбец «user_id».
Примечание: я получаю то же самое, когда пытаюсь удалить сделку, но тогда столбец ‘trade_id’
Я делаю то же самое для профессий и ролей пользователя, поэтому я думаю, что это связано с тем, что меня интересует. Я использую CascadeType.ВСЕ аннотации, позволяющие спящему режиму удалять связанные объекты
Списки связанных объектов в user:
@ManyToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinTable(name="user_roles",
joinColumns = { @JoinColumn(name = "user_id") },
inverseJoinColumns = { @JoinColumn(name = "role_id") })
private List<Role> roles = new ArrayList<>();
@Transient
@JsonIgnore
@OneToMany(cascade=CascadeType.ALL, mappedBy="user")
private List<Interest> interests = new ArrayList<>();
@Transient
@JsonIgnore
@OneToMany(cascade=CascadeType.ALL, mappedBy="user")
private List<Trade> trades = new ArrayList<>();
Объект интереса:
@Entity
@Table(name = "interests")
public class Interest {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int interestId;
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;
@ManyToOne
@JoinColumn(name = "trade_id", nullable = false)
private Trade trade;
private String comment;
public Interest(User user, Trade trade, String comment) {
this.user = user;
this.trade = trade;
this.comment = comment;
}
public Interest(){
}
}
Для сравнения, объект trade:
@Entity
@Table(name = "trades")
public class Trade {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="trade_id")
private int tradeId;
@Column(name="wants")
private String wants;
@Column(name="offers")
private String offers;
@Column(name="date_last_modified")
private LocalDateTime lastModified;
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;
@Transient
@JsonIgnore
@OneToMany(cascade=CascadeType.ALL, mappedBy="trade")
private List<Interest> interests = new ArrayList<>();
public Trade(String wants, String offers, User user){
this.wants = wants;
this.offers = offers;
this.user = user;
}
public Trade() {
}
}
У кого-нибудь есть идея о том, что я здесь делаю не так? Заранее спасибо
Ответ №1:
Попробуйте установить orphanRemoval
значение true
для следующих ассоциаций:
@OneToMany(cascade=CascadeType.ALL, mappedBy="user", orphanRemoval = true)
private List<Interest> interests = new ArrayList<>();
@OneToMany(cascade=CascadeType.ALL, mappedBy="user", orphanRemoval = true)
private List<Trade> trades = new ArrayList<>();
Как указано в документации:
Если жизненный цикл дочерней сущности привязан к ее родительскому элементу, так что дочерний элемент не может существовать без своего родительского элемента, тогда мы можем аннотировать ассоциацию с
orphanRemoval
атрибутом, и разъединение дочернего элемента также вызовет оператор delete для фактической строки дочерней таблицы.
Пожалуйста, также обратите внимание, что вы не должны использовать cascade=CascadeType.ALL
для @ManyToMany
ассоциации, как это объясняется в документации:
Для
@ManyToMany
ассоциацийREMOVE
переход состояния объекта не имеет смысла каскадировать, поскольку он будет распространяться за пределы таблицы ссылок. Поскольку на другую сторону могут ссылаться другие объекты на родительской стороне, автоматическое удаление может закончиться вConstraintViolationException
.