如何在删除该列表的项目后更新列表

Tha*_*ham 1 java jpa

我需要花一点时间解释一下,所以请和我在一起.我有NewsFeed一个与自己有OneToMany关系的表.

@Entity
public class NewsFeed(){
    ...
    @ManyToOne(optional=true, fetch=FetchType.LAZY)
    @JoinColumn(name="REPLYTO_ID")
    private NewsFeed replyTo;

    @OneToMany(mappedBy="replyTo", cascade=CascadeType.ALL)
    private List<NewsFeed> replies = new ArrayList<NewsFeed>();

    public void addReply(NewsFeed reply){        
       replies.add(reply);
       reply.setReplyTo(this);
    }

    public void removeReply(NewsFeed reply){
       replies.remove(reply);
    }
} 
Run Code Online (Sandbox Code Playgroud)

所以你可以这样想.每个Feed都有一个List也是类型的回复NewsFeed.现在,我很容易删除原始Feed并获取更新后的列表.删除后我需要做的就是这个.

feeds = scholarEJB.findAllFeed();  //This will query the db and return updated list
Run Code Online (Sandbox Code Playgroud)

但是在尝试删除replies并获取更新后的列表时遇到问题.所以这是我如何删除replies.在我的JSF托管bean里面

//Before invoke this method, I have the value of originalFeed, and deletedFeed set.
//These original feeds are display inside a p:dataTable X, and the replies are
//displayed inside p:dataTable Y which is inside X. So when I click the delete button
//I know which feed I want to delete, and if it is the replies, I will know
//which one is its original post
public void deleteFeed(){
    if(this.deletedFeed != null){
        scholarEJB.deleteFeeds(this.deletedFeed); 
        if(this.originalFeed != null){
            //Since the originalFeed is not null, this is the `replies`
            //that I want to delete
            scholarEJB.removeReply(this.originalFeed, this.deletedFeed);
        }
        feeds = scholarEJB.findAllFeed();
    }        
}
Run Code Online (Sandbox Code Playgroud)

然后在我的EJB学者EJB中,我有

public void removeReply(NewsFeed feed, NewsFeed reply){
    feed = em.merge(feed);
    comment.removeReply(reply);
    em.persist(comment);
}

public void deleteFeeds(NewsFeed e){
    e = em.find(NewsFeed.class, e.getId());
    em.remove(e);
    em.getEntityManagerFactory().getCache().evict(NewsFeed.class); //Like fdreger suggested
}
Run Code Online (Sandbox Code Playgroud)

当我离开时,实体(回复)被正确地从数据库中删除,但在feedsList中,reply仍然存在那个引用.只有在我退出并重新登录之后,回复才会消失.

fdr*_*ger 6

你写的是正确的,requerying应该工作(事实上它通常是如何做的),所以问题必须在其他地方.例如,如果您通过除remove方法之外的任何方式删除实体,它仍可能位于二级缓存中.或者可能因为一些小错误而没有发生重新征服?


更新:在阅读原始问题的新版本(包含所有新的来源和关于Eclipselink的说明)后,我做了一个小测试,它确实是 - 二级缓存问题.有点奇怪,可能是一个bug或一个未指定的角落案例.要解决此问题,请从缓存中删除注释:

// this goes after em.remove(e)
em.getEntityManagerFactory().getCache().evict(Comment.class);
Run Code Online (Sandbox Code Playgroud)

您也可以尝试逐出驱逐被删除实体的父级(有一个重载版本的evict).

Uhmpf.也许有更多街头信誉的人(BalusC?:-)应该在这篇文章中更改标签.原来它与JSF没什么关系.

  • 关于在JPA中驱逐单个实体的警告说明:``em.getEntityManagerFactory().getCache().evict(Comment.class);``.这是一个相当不安全的操作,因为它可能使缓存处于不一致状态.现在可能存在对未缓存对象的悬空引用.如果你需要驱逐使用evictAll,这是安全的. (2认同)