Этот вопрос задавали много раз раньше, но с тех пор я не видел удовлетворительного ответа, поэтому задаю его снова.
Представьте себе, следующая ситуация:
public class User {
...
@Cascade(value= {CascadeType.DELETE})
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name="followerId")
public List<LocationFollower> followedLocations;
...
}
public class LocationFollower {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false)
public Long id;
@ManyToOne
@JoinColumn(name="locationId")
public Location followedLocation;
@ManyToOne
@JoinColumn(name="followerId")
public User follower;
@Column(name = "followerSince")
public Timestamp followerSince;
}
public class Location {
...
@Cascade(value = {CascadeType.DELETE})
@OneToMany(fetch= FetchType.LAZY)
@JoinColumn(name="locationId")
public List<LocationFollower> followers;
...
}
Все, что я хотел, это удалить пользователя. Логично предположить, что все связанные записи «последователей», связывающие пользователя и местоположение, будут удалены. То же предположение должно остаться в силе, если я удалю запись о местоположении.
На самом деле происходит то, что Hibernate пытается обновить (?!?) Таблицу, в которой хранятся подписчики, и, поскольку связанный объект (Пользователь или Местоположение) был отправлен на удаление, пытается установить внешний ключ, например followerId с нулем. Это вызывает исключение и прерывает все последующие операции.
Я получаю ошибку: На сервере произошел необработанный сбой. Не удалось выполнить пакетное обновление JDBC; SQL [обновить locationstofollowers установить followerId = null, где followerId =?]; ограничение [null]; вложенное исключение - org.hibernate.exception.ConstraintViolationException: не удалось выполнить пакетное обновление JDBC
PS Я слышал, что был другой каскадный параметр DELETE_ORPHAN. Кажется, это устарело, и хотя я тоже пробовал, эффект был тот же.