0

Я застрял в точке, где я пытаюсь обновить отображение @OneToMany.Проблема при обновлении коллекции @OneToMany

Проблема: У меня есть 2 объекта: критерии и задачи. Критерии могут содержать несколько задач.

class Criteria { 
    @OneToMany(mappedBy = "criteria", cascade = { CascadeType.PERSIST, 
    CascadeType.MERGE, CascadeType.REFRESH }, fetch = FetchType.LAZY) 
    @Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE, 
       org.hibernate.annotations.CascadeType.ALL, 
       org.hibernate.annotations.CascadeType.MERGE, 
       org.hibernate.annotations.CascadeType.PERSIST }) 
    private Set<Task> tasks; 
} 

class Task { 
    @ManyToOne 
    @JoinColumn(name = "CRITERIA_ID", nullable=false) 
    private Criteria criteria; 
} 

Я пытаюсь обновить существующие критерии с помощью нового набора задач. Это требует удаления всех существующих задач и добавления новых задач. Вот как я делаю:

criteriaDao.persist(criteria); 
Set<Task> existingTasks=criteria.getTasks(); 
if(existingTasks != null) { 
    for (Task task : existingTasks) { 
     task.setCriteria(null); 
    } 
    criteria.setTasks(tasks); 
    //more code which sets criteria for each task - this works if i try to save new criteria with new tasks 
} 

Hibernate бросает исключение:

Caused by: java.sql.BatchUpdateException: ORA-00001: unique constraint (CCA_DEV_5.TASK__UN) violated 

Это исключение, потому что она не устранила существующие задачи.

Если я только удалить все задачи, она прекрасно работает и удалить все задачи по заданным критериям с ниже кодом:

criteriaDao.persist(criteria); 
Set<Task> existingTasks=criteria.getTasks(); 
if(existingTasks != null) { 
    for (Task task : existingTasks) { 
    task.setCriteria(null); 
} 
} 

Я перепробовал все варианты использования слияния после добавления новых задач и больше вещей, но для меня ничего не работает. Я плохо застрял здесь и, несомненно, пропустил что-то очень важное в Hibernate.

Заранее спасибо.!

ответ

0

В вашем классе Task вы не должны иметь ссылки на Criteria. Просто удалите его вместе со своими аннотациями.

Затем, вместо установки Criteria, на который ссылается Task, так как эта ссылка больше не существует, просто использовать criteria.setTasks(newTasks) и сохранить criteria.


Позвольте мне немного пояснить. Отношение между Criteria и Task является obvoiusly Criteria 1 --- n Tasks - от 1 до n. Теперь вы можете позвонить по телефону one-to-many, и вы можете назвать это many-to-one, в зависимости от вашей точки зрения. Взгляд с Criteria в виду, это one-to-many, глядя с Task Точка зрения - это many-to-one. Как правило, целесообразно и интуитивно выбрать один из этой точки зрения и придерживаться его. Выбирая точку зрения, определяет объект, который «контролирует» отношение, которое должно быть применено к любой модификации.

В вашем случае, если вы расцениваете Criteria, как содержащего или владеющего набор Task с - вы бы рассматривать отношения, как one-to-many. После принятия решения, нет необходимости в Criteria ссылка в классе java из Task. Вы контролируете связь только с API Criteria (таблица, созданная для Task в БД, однако имеет колонку, которая ссылается на ее содержащий Criteria).

+0

Хм ... многие-к-одному, на мой взгляд, должны работать вместе с одним-ко-многим, я не видел никаких проблем с ним. Также JPA поддерживает обратное отображение.Я исправил это, добавив следующие строки перед установкой коллекции с новой коллекцией наборов - для (Задача задачи: существующие задачи) { task.setCriteria (null); } => session.flush(); criteria.setTasks (задачи); Это гарантирует, что операторы удаления выполняются перед вставками. –

+0

@ RakeshSinha здорово, что вы решили проблему. Тем не менее, я бы рекомендовал вам прочитать [этот короткий пример документа спящего родителя и ребенка) (http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#example-parentchild-bidir) в котором объясняется, как использовать 'inverse' в отношении' one-to-many'. – yair

+0

Спасибо, я видел этот документ в прошлом и использовал его. Как вы думаете, есть ли еще один способ добиться того, что я делаю? Вызов flush() явно работает, но это приведет к тому, что диспетчер сущностей сбросит все запросы на Db. Есть ли лучший способ обновления коллекции? –