Удаление из таблицы с аннотацией @OneToOne - PullRequest
5 голосов
/ 03 января 2011

Я использую JPA2 и реализацию Hibernate.

У меня есть простое отображение как это:

@Entity 
class Topic {

    @Id
    @GeneratedValue(strategy = IDENTITY)

    int id;

   @OneToOne(cascade = ALL)
   @JoinColumn(name = "id_poll")
   private Poll poll;

}

@Entity 
class Poll {
    @Id
    @GeneratedValue(strategy = IDENTITY)
    int id;
}

Теперь, когда я удаляю объект опроса, который также находится в теме, я получаю сообщение об ошибке.

java.sql.SQLException: нарушение ограничения целостности. Таблица FKCC42D924982D3F4B: ТЕМЫ в выражении [удалить из опросов, где id =?]

Я понимаю, что это потому, что я не могу удалить запись опроса, если в ней есть ссылки в другой таблице. Как я могу решить эту проблему? Нужно ли вручную устанавливать poll = null в таблице тем или есть лучшее решение?

Ответы [ 4 ]

6 голосов
/ 25 августа 2012

Это ожидаемое поведение:

Распространенной проблемой двунаправленных отношений является то, что приложение обновляет одну сторону отношения, но другая сторона не обновляется и не синхронизируется.В JPA, как и в Java в целом, это ответственность приложения или объектной модели за поддержание отношений .

Источник: Повреждение объекта, одна сторонасвязь не обновляется после обновления другой стороны

Правильное место для обработки этого - обратный вызов @PreRemove:

@Entity 
class Poll {

    ...

    @PreRemove
    private void preRemove() {
        Poll poll = topic.getPoll();
        topic.setPoll( null );
    }
}

См. также: Есть JPA /Спящий режим для репликации функции «ON DELETE SET NULL»

1 голос
/ 04 января 2011

Мне пока не удалось найти решение, поэтому перед удалением объекта опроса я всегда получаю объект Topic, который содержит данный пул, и присваиваю ему значение null.

Topic topic = entityManager.find( Topic.class, 1 );
Poll poll = topic.getPoll();
topic.setPoll( null );
entityManager.remove( poll );

И он работает правильно.

1 голос
/ 03 января 2011

Похоже, что аннотация @OneToOne в JPA 2 содержит флаг orphanRemoval, вы можете попробовать установить его и посмотреть, удаляет ли он его изящно.

0 голосов
/ 20 декабря 2011

Проблема заключается в том, что вы используете автоматически сгенерированный идентификатор с обеих сторон. Когда вы сохраняете родительский объект, дочерний объект также сохраняется, но его идентификатор внутри родительского объекта не обновляется с идентификатором, сгенерированным из базы данных.

В результате, когда вы удаляете родителя, вы не удаляете ребенка, потому что у ребенка нет идентификатора.

Попробуйте установить вручную идентификатор дочерней сущности, и orphanRemoval будет работать.

...