删除然后在JPA/Hibernate中查询失败(已删除的实体传递给持久化)

Kev*_*vin 2 java hibernate jpa

我在我的JPA应用程序中删除实体时遇到了问题:基本上,我在这个EJB Business方法中做了:

load photo list ;
for each photo {
    //UPDATE
    remove TagPhoto element from @OneToMany relation
    //DISPLAY
    create query involving TagPhoto
    ...
}
Run Code Online (Sandbox Code Playgroud)

并且这最后一个查询总是抛出一个EntityNotFoundException(已删除的实体传递给persist:[... TagPhoto#])

我想我理解这个异常的含义,比如我的Remove引起的同步问题,但我怎么能摆脱它呢?

编辑:这是异常的堆栈:

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)
Run Code Online (Sandbox Code Playgroud)

以及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;
}
Run Code Online (Sandbox Code Playgroud)

(当我创建项目时,它是由Netbeans自动生成的)

编辑:这是什么意思tagPhoto != tagPhoto.getTag().getTagPhotoList().get(...) != tagPhoto.getPhoto().getTagPhotoList().get(...)

我该如何删除它们?iterator.remove不应该有任何用处,我认为三个em.remove()会做同样操作的三倍......

Pas*_*ent 7

说实话,没有映射(特别是级联选项)很难说,没有精确的堆栈跟踪和没有真正的代码,因为伪代码很可能不会显示真正的问题.所以这个答案更像是黑暗中的一个镜头(你应该考虑发布上面提到的细节).

我的猜测是你正在调用remove()一个TagPhoto你没有从一对多关联中删除的实例.因此,当EntityManager尝试更新父Photo时,它可能确实尝试保留已删除的实体,因此异常.

更新:您需要TagPhoto从包含它的两个集合中删除该实例:

photo.getTagPhotoList().remove(tagPhoto);
...
tag.getTagPhotoList().remove(tagPhoto);
...
em.remove(tagPhoto);
Run Code Online (Sandbox Code Playgroud)

请注意,事实上实际上有点复杂,因为NetBeans为连接表(TagPhoto)生成了一个实体.如果你Photo和之间有多对多的关联会更容易一些Tag.但无论如何,当您删除实体时,您需要将其从关联中删除,JPA不会为您执行此操作.