我需要花一点时间解释一下,所以请和我待在一起。我有一个与自己有OneToMany关系的表NewsFeed
。
@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);
}
}
所以你可以这样思考。每个Feed都可以有List
个回复,这些回复也是NewsFeed
类型。现在,我很容易删除原始Feed并获取更新后的列表。删除后我需要做的就是这个。
feeds = scholarEJB.findAllFeed(); //This will query the db and return updated list
但是在尝试删除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();
}
}
然后在我的EJB scholarEJB中,我有
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
}
当我离开时,实体(回复)被正确地从数据库中删除,但在feeds
列表中,仍然存在那个reply
的引用。只有在我退出并重新登录之后,回复才会消失。
答案 0 :(得分:6)
你写的是正确的,requerying应该工作(事实上它通常是如何做的),所以问题必须在其他地方。例如,如果您通过除remove方法之外的任何方式删除实体,它仍可能位于二级缓存中。或者可能因为一些小错误而没有发生重新征服?
更新:在阅读原始问题的新版本(包含所有新来源和有关Eclipselink的说明)后,我做了一点测试,实际上是二级缓存问题。有点奇怪,可能是一个bug或一个未指定的角落案例。要修复它,请从缓存中删除注释:
// this goes after em.remove(e)
em.getEntityManagerFactory().getCache().evict(Comment.class);
您也可以尝试逐出驱逐被删除实体的父级(有一个重载的驱逐版本)。
Uhmpf。也许有更多街头信誉的人(BalusC?:-)应该在这篇文章中更改标签。原来它与JSF没什么关系。
答案 1 :(得分:3)
删除对象时,必须先删除对该对象的所有引用,然后才能删除它。如果不这样做,则可能会在持久性上下文或二级缓存中出现约束错误或过时数据。
删除Feed时,首先将其从回复中删除。