Удалить, а затем выполнить запрос в JPA / Hibernate (удаленная сущность передана для сохранения) - PullRequest
2 голосов
/ 30 мая 2010

У меня проблема с удалением сущностей в моем приложении JPA: в основном я использую этот метод EJB Business:

load photo list ;
for each photo {
    //UPDATE
    remove TagPhoto element from @OneToMany relation
    //DISPLAY
    create query involving TagPhoto
    ...
}

, и этот последний запрос всегда вызывает исключение EntityNotFoundException (удаленная сущность, переданная для сохранения: [... TagPhoto #])

Мне кажется, я понимаю значение этого исключения, как проблема синхронизации, вызванная моим удалением, но как я могу от нее избавиться?

РЕДАКТИРОВАТЬ: вот стек исключений:

Caused by: javax.persistence.EntityNotFoundException: deleted entity passed to persist: [net.wazari.dao.entity.TagPhoto#<null>]
    at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:621)
    at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:74)
    at net.wazari.dao.jpa.TagFacade.loadVisibleTags(TagFacade.java:108)

и отображение между Tag-TagPhoto-Photo

public class Tag implements Serializable {
    ...
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "tag")
    private List<TagPhoto> tagPhotoList;
}
public class TagPhoto implements Serializable {
    ...
    @JoinColumn(name = "Tag", referencedColumnName = "ID")
    @ManyToOne(optional = false)
    private Tag tag;
    @JoinColumn(name = "Photo", referencedColumnName = "ID")
    @ManyToOne(optional = false)
    private Photo photo;
}
public class Photo implements Serializable {
    ...
    @OneToMany(cascade = CascadeType.ALL , mappedBy = "photo")
    private List<TagPhoto> tagPhotoList;
}

(он был автоматически сгенерирован Netbeans при создании проекта)

РЕДАКТИРОВАТЬ: Означает ли это, что tagPhoto != tagPhoto.getTag().getTagPhotoList().get(...) != tagPhoto.getPhoto().getTagPhotoList().get(...)?

и как мне их удалить? iterator.remove не должен быть бесполезным, и я думаю, что три em.remove() будут делать три раза одну и ту же операцию ...

Ответы [ 3 ]

7 голосов
/ 30 мая 2010

Честно говоря, трудно сказать без отображений (особенно каскадных опций), без точной трассировки стека и без реального кода, поскольку псевдокод, скорее всего, не показывает реальной проблемы. Таким образом, этот ответ - скорее выстрел в темноте (и вы должны рассмотреть возможность размещения упомянутых деталей).

Я предполагаю, что вы вызываете remove() для TagPhoto экземпляра, который вы не удаляете из ассоциации один-ко-многим. Поэтому, когда EntityManager пытается обновить родительскую фотографию, он действительно может попытаться сохранить удаленную сущность, отсюда исключение.

Обновление: Вам необходимо удалить экземпляр TagPhoto из обеих коллекций, в которых он содержится:

photo.getTagPhotoList().remove(tagPhoto);
...
tag.getTagPhotoList().remove(tagPhoto);
...
em.remove(tagPhoto);

Обратите внимание, что на самом деле все немного сложнее, потому что NetBeans сгенерировал Entity для таблицы соединения (TagPhoto). Было бы немного проще, если бы у вас была связь «многие ко многим» между Photo и Tag. Но в любом случае, когда вы удаляете сущность, вам нужно удалить ее из ассоциаций, JPA не сделает этого за вас.

1 голос
/ 30 мая 2010

Может быть проблема с синхронизацией. Попробуйте позвонить Session.flush() перед созданием TagPhoto.

0 голосов
/ 08 мая 2011

Я столкнулся почти с похожей ситуацией и решил ее, просто удалив ссылки со стороны владельца. Теперь в вашем случае TagPhoto является владельцем как отношений для Tag, так и для Photo. Все, что вам нужно сделать, это запросить TagPhoto с любой стороны, удалить его и обновить ссылку на стороне владельца.

например в каком-то сервисе, который покрывается

    for(TagPhoto tagPhoto : photo.getTagPhotoList()){

    boolean update = false;

    for(Iterator<TagPhoto> iterator = 

    tagPhoto.getPhoto().getTagPhotoList().iterator();

    iterator.hasNext();){
            TagPhoto tagPhoto2 = iterator.next();
            if(tagPhoto.getId() == tagPhoto2.getId()){
                iterator.remove();
                update = true;
            }
        }

        if(update){
            tagPhoto.setPhoto(null);
            tagPhoto.setTag(null);
            tagPhotoService.remove(tagPhotoService.update(tagPhoto));
        }
    }

Также убедитесь, что вы не вызываете entityManager.flush () явно из любого из ваших API. Он должен вызываться транзакциейManager. После завершения транзакции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...