2010-12-31 4 views
1

Es wird einen Moment dauern, bis ich das erkläre, also bleiben Sie bitte bei mir. Ich habe Tabelle NewsFeed, die OneToMany Beziehung mit sich hat.So aktualisieren Sie die Liste nach dem Löschen eines Elements dieser Liste

@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); 
    } 
} 

So können Sie so denken. Jeder Feed kann einen List von Antworten haben, die auch vom Typ NewsFeed sind. Jetzt ist es sehr einfach für mich, den ursprünglichen Feed zu löschen und die aktualisierte Liste zurück zu bekommen. Alles, was ich nach dem Löschen tun muss, ist dies.

feeds = scholarEJB.findAllFeed(); //This will query the db and return updated list 

Aber ich Problem habe, wenn sie versuchen replies zu löschen und die aktualisierte Liste immer wieder. Also hier ist, wie ich die replies löschen. In meinem JSF Bean verwaltet habe ich

//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(); 
    }   
} 

Dann in meinem EJB scholarEJB, ich habe

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 
} 

Wenn ich raus, bekommt das Unternehmen (die Antwort) aus der Datenbank korrekt entfernt, aber innerhalb der feeds Liste, Referenz reply immer noch da. Erst wenn ich mich abmelde und mich wieder einloggen, verschwindet die Antwort.

Antwort

6

Was Sie geschrieben haben, ist richtig, Requerying sollte funktionieren (und in der Tat, wie es normalerweise getan wird), so muss das Problem woanders sein. Wenn Sie beispielsweise die Entität auf andere Weise als die remove-Methode löschen, befindet sie sich möglicherweise noch im Cache der zweiten Ebene. Oder vielleicht findet das Requerying aufgrund eines kleinen Fehlers gar nicht statt?


aktualisieren: Nach der neuen Version der ursprünglichen Frage zu lesen (mit all den neuen Quellen und Klärung über Eclipse) machte ich einen kleinen Test, und es ist - in der Tat - ein Second Level Cache Problem. Ein bisschen seltsam und möglicherweise entweder ein Fehler oder ein unterspezifizierter Eckfall. Um es zu beheben, vertreiben Kommentare aus dem Cache:

// this goes after em.remove(e) 
em.getEntityManagerFactory().getCache().evict(Comment.class); 

Sie könnten auch versuchen, die Eltern der entfernten Einheit evicting nur (es gibt eine überladene Version von evict).

Uhmpf. Vielleicht sollte jemand mit mehr Street Cred (BalusC? :-) Tags in diesem Beitrag ändern. Es stellte sich heraus, dass es nichts mit JSF zu tun hat.

+0

Danke. Ich lösche die Entität durch 'remove' Methode. Wenn ich den ursprünglichen Post lösche, funktioniert es großartig. Entity wurde entfernt, die Liste wurde aktualisiert. Nicht sicher, warum es nicht mit den Antworten funktioniert. Kannst du mehr über den 2nd Level Cache sprechen? –

+0

Es ist entweder ein großer Fehler in Ihrer JPA-Implementierung (aus der Verwendung von faul zu beurteilen, könnte es Eclipselink sein - ist es?), Oder ein großer Fehler in Primefaces oder ein kleiner Fehler in Ihrer Anwendung. Versuchen Sie und debuggen Sie (ein paar out.printlns in einer for-Schleife wird tun) den Wert von myEJB.getAllComments zurückgegeben. Auf diese Weise werden Sie wissen: 1) wenn die Methode überhaupt aufgerufen wird, 2) wenn die zurückgegebenen Daten gut aussehen (mein Shoot ist, dass es überhaupt nicht aufgerufen wird) – fdreger

+0

Yup es ist eclipselink, ich werde tun, was Sie sagten.Zurück in ein bisschen –

3

Wenn Sie ein Objekt löschen, müssen Sie alle Referenzen auf dieses Objekt löschen, bevor Sie es löschen. Wenn Sie dies nicht tun, können Sie einen Beschränkungsfehler oder veraltete Daten in Ihrem Persistenzkontext oder im Cache der zweiten Ebene erhalten.

Wenn Sie den Feed entfernen, entfernen Sie ihn zuerst aus den Antworten.

+0

das könnte mein Problem auch sein. Wenn Sie sich meinen Code ansehen. Ich entferne den Feed zuerst und entferne ihn dann aus den Antworten. Willst du damit sagen, dass es funktionieren wird, wenn ich den Auftrag umgebe. Wie es gerade jetzt ist, benutze ich, was fdreger vorschlagen, und verwerfe Second-Level-Cache. Es funktioniert gerade jetzt. Aber es ist auch gut zu wissen, ob es andere Wege gibt –

Verwandte Themen