#java #hibernate
#java #hibernate
Вопрос:
У меня есть три объекта Hibernate:
- Обложка
- Песня
Песня представляет собой файл песни (например, файл mp3), обложка содержит обложку песни, песня может содержать несколько фрагментов обложки
В песне я определяю ссылку на обложку как:
@OneToMany(fetch=FetchType.LAZY, cascade={CascadeType.ALL})
@JoinColumn(name = "recNo")
private List<CoverArt> coverArts;
В CoverArt нет ссылки, определенной на песню, у нас просто есть
@Id
@GeneratedValue
private Integer id;
Приложение работает нормально, за исключением случаев, когда я хочу очистить объекты Song и CoverArt.
Это происходит не всегда, но если я сначала попытаюсь удалить из песни
e.g
String hql = String.format("delete from CoverArt");
Query query = session.createQuery(hql);
query.executeUpdate();
hql = String.format("delete from Song");
query = session.createQuery(hql);
query.executeUpdate();
session.getTransaction().commit();
Я получаю исключение:
Вызвано: org.h2.jdbc.JdbcSQLException: нарушение ограничения ссылочной целостности: «FK_CBUK1UQ1D0DQAA077XH16SRX2: ВНЕШНИЙ КЛЮЧ PUBLIC.SONG_COVERART (COVERARTS_ID) ССЫЛАЕТСЯ НА PUBLIC.COVERART(ID) (13)»; Инструкция SQL:
и если я попробую другим способом
String hql = String.format("delete from Song");
Query query = session.createQuery(hql);
query.executeUpdate();
hql = String.format("delete from CoverArt");
query = session.createQuery(hql);
query.executeUpdate();
Я получаю исключение
Вызвано: org.h2.jdbc.JdbcSQLException: нарушение ограничения ссылочной целостности: «FK_4B4O39V3RSF1IWWRIX6QQQTLK: ВНЕШНИЙ КЛЮЧ PUBLIC.SONG_COVERART (SONG_RECNO) ССЫЛАЕТСЯ НА PUBLIC.SONG(RECNO) (1)»; Оператор SQL:
Таким образом, невозможно очистить таблицы, объект CoverArt существует только как часть песни, поэтому я предположил, что это будет только внешний ключ из таблицы COVER_ART в таблицу SONG, и ожидал, что смогу удалить все из CoverArt без проблем, но есть промежуточная таблица, созданная SONG_COVERART, которая имеет внешние ключи к обеим таблицам, предотвращающие удаление.
Что я делаю не так (используя Hibernate 4.3.11)
Комментарии:
1. Вероятно, потому, что в предыдущей версии вашего кода не было аннотации JoinColumn, и Hibernate, таким образом, создал таблицу объединения для этой ассоциации, которую вы заполнили, но забыли удалить.
2. @JBNizet Я думаю, у вас это есть, потому что я сам не видел ошибку, только некоторые клиенты, и я только что включил hibernate.show_sql и воссоздал базу данных, и нет таблицы SONG_COVERART, если вы хотите опубликовать ответ, я отмечу как правильный.
3. @JBNizet ах, итак, воссоздаю базу данных с конфигурацией config = getInitializedConfiguration(); config.setProperty(Environment. HBM2DDL_AUTO, «создать»); не решит проблему, потому что проблемная таблица все еще будет существовать, поскольку Hibernate больше не знает об этом, поэтому я просто вручную добавляю оператор SQL drop?
4. Я бы никогда не использовал hbm2ddl для работы с реальной производственной базой данных, содержащей данные. Это хорошо для быстрого прототипирования, но не для поддержания реальной базы данных с данными, которые должны быть должным образом перенесены. FlywayDB и Liquibase — гораздо лучшие инструменты, предназначенные для этого.
5. @JBNizet Я посмотрю на это, но это всего лишь база данных приложения, которую обычно не нужно сохранять более нескольких недель за раз, пожалуйста, подтвердите, что мне придется выполнять отдельное удаление
Ответ №1:
Вероятно, потому, что в предыдущей версии вашего кода не было аннотации JoinColumn, и Hibernate, таким образом, создал таблицу объединения для этой ассоциации, которую вы заполнили, но забыли удалить.