Frage

Schnellversion

Im Grunde aktualisiere ich eine Ruhezustandstabelle und nachfolgende Abfragen laden einen veralteten Wert.

Detaillierte Version

Hibernate (3.3.1.GA) und EhCache (2.4.2).

Beharrte Book Objekt mit a List<PageContent> Seitenzahl und ich füge eine Seite in der Mitte dieses Buches hinzu.Ich verwende Databinder/Wicket, obwohl ich nicht glaube, dass das damit zusammenhängt.

 public void createPageContent(Book book, int index) {
     Databinder.getHibernateSession().lock(book, LockMode.UPGRADE);
     PageContent page = new PageContent(book);
     book.addPage(page, index);
     CwmService.get().flushChanges(); // commits the transaction
 }

Die anwendbaren Felder/Methode in Book Sind:

@OneToMany
@JoinColumn(name="book_id")
@IndexColumn(name="pageNum")
@Cascade({CascadeType.ALL, CascadeType.DELETE_ORPHAN})
private List<PageContent> pages = new ArrayList<PageContent>();

public synchronized void addPage(PageContent page, int index) {
    pages.add(index, page);
}

Das Endergebnis ist, dass einer Liste eine neue Seite hinzugefügt wird und die Datenbank entsprechend aktualisiert wird, und ich habe dies in meinem Datenspeicher bestätigt.Bei der nächsten Abfrage für eine Seite, beispielsweise „Seite Nr. 4“, wird jedoch die „alte“ Seite Nr. 4 anstelle der neuen Seite Nr. 4 geladen:

criteria.add(Restrictions.eq("book", book));
criteria.add(Restrictions.eq("pageNum", pageNum));
criteria.setCacheable(true);  

Daher entferne ich widerwillig Caching aus den Kriterien.Es fragt den Datenspeicher ab, aber gibt immer noch den falschen Wert zurück.Wenn ich jedoch in beiden Fällen etwa 2 Minuten warte, funktioniert alles wie erwartet.Ich gehe davon aus, dass es immer noch um Caching geht.Beide PageContent Und Book Verwenden Sie diese Caching-Strategie:

@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)

Ich gestehe, ich bin neu im Caching und habe diese Datei gerade zum ersten Mal eingerichtet.Hier ist meine ehcache.xml:

<defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" statistics="false"/>

<!-- Hibernate's Cache for keeping 'lastUpdated' data on each table.  Should never expire. -->
<cache name="org.hibernate.cache.UpdateTimestampsCache" eternal="true" />

<!-- Hibernate's Query Cache - should probably be limited -->
<cache name="org.hibernate.cache.StandardQueryCache" maxElementsInMemory="1000" />

AKTUALISIEREN:Entferne den @Cache Anmerkungen zu meinen Datenspeicherobjekten beseitigen das Problem.Natürlich möchte ich diese Objekte zwischenspeichern, da Seitenänderungen viel seltener sind als Zugriffe.

Also, Gedanken?Es gibt auch mehrere andere damit verbundene Probleme, unter anderem beim Löschen von Seiten.Alles aktualisiert die Datenbank wie erwartet, aber das tatsächliche Verhalten ist seltsam.

Dank im Voraus!

UPDATE Nr. 2:Durch das Debuggen kann ich bestätigen, dass der Datenspeicher über die richtigen Informationen verfügt, und wenn die Abfrage ausgeführt wird, greift sie auf den Second-Level-Cache zurück, der fehlerhafte Informationen enthält.Ich gehe davon aus, dass es nicht an mir liegt, jedes Mal, wenn sich die Daten ändern, den Cache zu löschen?

War es hilfreich?

Lösung 2

Ich habe das Problem entdeckt, aber es bringt etwas anderes mit sich.

Grundsätzlich gilt: Beim Ändern von a Book Objekt List<PageContent> Feld macht Hibernate drei Dinge:

  1. Lässt den TimeStamp-Cache-Eintrag für beide ablaufen Book Und PageContent
  2. Führt viele Abfragen durch, um das zurückzusetzen pageNum Feld auf jedem PageContent Objekt
  3. Entfernt die Book Objekt aus dem Second Level Cache.

Dadurch wird sichergestellt, dass nachfolgende Abfragen nach neuen Objekten usw. suchen.Jedoch:

  1. Der Ruhezustand entfernt nicht jede neu nummerierte Datei PageContent Objekt aus dem Second Level Cache

Infolgedessen wird jede Abfrage für die Seitenliste ordnungsgemäß ausgeführt, greift dann jedoch auf veraltete Second-Level-Cache-Werte für die tatsächlichen Daten zurück.

Ich vermute, das liegt daran, dass sich Hibernate a anfühlt pageNum Veränderung ist keine Änderung der Daten, sondern eine Änderung des Managements hinter den Kulissen.Das sind jedoch die Daten, die ich lesen und anzeigen möchte.

Die Lösung besteht darin, jede Seite nach dem Einfügen/Löschen manuell zu aktualisieren.

Andere Tipps

Nach CwmService.get().flushChanges(); // commits the transaction Führen Sie ein explizites Commit durch.flush() Die Änderungen werden nur in die Datenbank geschrieben, aber nicht festgeschrieben.Ich bin mir nicht sicher flushChanges() obwohl.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top