У меня есть объект A
с набором базовых типов (например, String
). Я использую такое сопоставление, потому что строки, связанные с каждым экземпляром A
, зависят от жизненного цикла A
. Если я хочу удалить экземпляр A
из БД, я также хочу, чтобы связанные с ним String
были удалены.
Мое отображение выглядит следующим образом:
@Entity
public class A {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "name", nullable = false, unique = true)
private String name;
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "AStrings", joinColumns = @JoinColumn(name = "id"))
@Column(name = "strings", nullable = false)
private Set<String> strings;
}
Если я создам экземпляр A
и добавлю в него несколько строк, я смогу сохранить экземпляр, используя Session.save(myInstance)
. И экземпляр A
, и связанные с ним String
сохраняются.
Но если я хочу удалить тот же экземпляр из БД, используя Session.createQuery("delete A a where a.name = ?").setString(0, name).executeUpdate()
, я получаю ошибку ограничения внешнего ключа:
Невозможно удалить или обновить родительскую строку: ограничение внешнего ключа не работает
Но я ожидаю, что связанные String
будут автоматически удалены перед удалением экземпляра A
, но, похоже, это не так. Я также не нашел способа указать каскадные правила.
Что-то не так с моей конфигурацией?
Спасибо
EDIT: я также пытался использовать @Cascade(CascadeType.DELETE)
в поле strings
, и это все еще не помогает. Просматривая базу данных, я не вижу никакой политики ON DELETE
для соответствующего внешнего ключа.
Кто-то, у кого была такая же проблема, открыл JIRA: https://hibernate.onjira.com/browse/HHH-4301. Решение (или обходной путь) должно существовать, я не могу быть единственным человеком, который использует @ElementCollection
.
Я решил проблему. Я думал, что удаление с помощью Session.delete() или с помощью запроса HQL эквивалентно, но, похоже, это не так. Используя запрос HQL, зависимые объекты не удаляются автоматически, поэтому я получаю ошибку ограничения внешнего ключа. Использование Session.delete() решает проблему. Кроме того, Hibernate, похоже, не использует каскадные функции БД, поскольку я до сих пор не вижу никакой политики CASCADE в сгенерированном DDL, он обрабатывает это внутри.