2015-07-16 5 views
2

У меня есть 3 объекта, Party, сопоставленный с одним номером с Invitation, который отображается как многоToOne с Guest. Определения JPA являются:Невозможно удалить сопоставленный объект, Hibernate JPA

партии Класс

@OneToMany(mappedBy="party", targetEntity=com.acme.party.model.Invitation.class) 
@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.LOCK}) 
@org.hibernate.annotations.LazyCollection(org.hibernate.annotations.LazyCollectionOption.FALSE) 
private java.util.Set invitation = new java.util.HashSet(); 

Приглашение класса

@ManyToOne(targetEntity=com.acme.party.model.Party.class) 
@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.LOCK})  
@JoinColumns({ @JoinColumn(name="partyId", referencedColumnName="partyId", nullable=false) }) 
private com.acme.party.model.Party party; 

@ManyToOne(targetEntity=com.acme.party.model.Guest.class) 
@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.LOCK})  
@JoinColumns({ @JoinColumn(name="guestId", referencedColumnName="guestId", nullable=false) }) 
private com.acme.party.model.Guest guest; 

Гость Класс

@OneToMany(mappedBy="guest", targetEntity=com.acme.party.model.Invitation.class)  
@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.LOCK}) 
@org.hibernate.annotations.LazyCollection(org.hibernate.annotations.LazyCollectionOption.FALSE) 
private java.util.Set invitation = new java.util.HashSet(); 

В экспортируемой базе данных, все внешние ключи устанавливаются on update cascade, on delete cascade

Моя проблема:

Внутри метода пользовательских обновлений, я пытаюсь удалить приглашения из Сторон. Удаляя Invitation объектов с сайта party.invitations и представляя party, я замечаю, что удаленные Invitations все еще там.

party.getInvitation().remove(invitation12); 
party.getInvitation().remove(invitation23); 
session.saveOrUpdate(party); 

К дополнительно удаление приглашения

party.getInvitation().remove(invitation12); 
party.getInvitation().remove(invitation23); 
session.delete(invitation12); 
session.delete(invitation23); 
session.saveOrUpdate(party); 

Я получаю PersistentException:

org.orm.PersistentException: org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [com.acme.party.model.Invitation#923] 

Что я делаю неправильно? Должен ли я беспокоиться об ассоциациях, которые существуют в коде моего метода обновления, например. временные HashMaps, которые я использую для повторения приглашений? Или я должен пересмотреть мою каскадную стратегию?

+0

1) Как вы получаете экземпляры 'приглашение12' и' приглашение23'? 2) После вызова 'party.getInvitation(). Remove (приглашение12);', 'приглашение12 'все еще находится в' party.getInvitation() 'set? –

+0

@DraganBozanovic 1) Я получаю их от 'party.getInvitation()', хотя я итерации через них пару раз, перекрестные проверки с другой коллекцией. 2) Да, я уверен, что 'party.getInvitation()' не содержит их прямо перед тем, как я вызову 'session.saveOrUpdate (party)' – yannicuLar

+0

Не могли бы вы разместить 'hashCode' и' equals' 'Invitation'? –

ответ

0

Вы столкнулись с известной проблемой, исходящей из JPA 1.0 (и она останется в будущих версиях JPA для обеспечения совместимости).

JPA 2.0 обеспечивает обходной путь для этого дефекта: вы можете добавить атрибут orphanRemoval=true к определению oneToMany явно запросить удаление дочерних сущностей, когда они будут удалены из коллекции:

@OneToMany(orphanRemoval=true, mappedBy="party", targetEntity=com.acme.party.model.Invitation.class) 
... 
private java.util.Set invitation = new java.util.HashSet(); 
+0

Какая проблема? –

+0

Мне показалось, что 'orphanRemoval' осталось там в основном для совместимости со старым JPa, но вы могли (и, вероятно, должны) избегать его использования в JPA 2 – yannicuLar

+0

К сожалению, нет. Проблема заключается в том, что модель * JPA-1.0 * не должна внезапно вести себя по-разному, когда она работает с поставщиком JPA-2. – ben75

0

Я управляемом чтобы удалить приглашения, удалив их из отображения guest.getInvitation(). Похоже, что это была ассоциация, которая оставалась неизменной, сохраняя invitation.

party.getInvitation().remove(invitation12); 
party.getInvitation().remove(invitation23); 

guest1.getInvitation().remove(invitation12); 
guest2.getInvitation().remove(invitation23); 

session.delete(invitation12); 
session.delete(invitation23); 
session.saveOrUpdate(party); 

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

Смежные вопросы