2008-09-07 9 views
7

Unser Entwurf hat eine jvm, die eine jboss/webapp (lesen/schreiben) ist, die verwendet wird, um die Daten über Hibernate (mit jpa) an die db zu pflegen. Das Modell verfügt über 10-15 persistente Klassen mit 3-5 Tiefenstufen in den Beziehungen.Wie kann die Hibernate-Cache-Konsistenz beibehalten werden, indem zwei Java-Anwendungen ausgeführt werden?

Wir haben dann eine separate jvm, die der Server mit diesen Daten ist. Da es kontinuierlich läuft, haben wir nur eine lange db Sitzung (nur lesen).

Es ist derzeit kein intra-jvm-Cache vorhanden - also signalisieren wir manuell einen jvm von dem anderen.

Wenn der Webapp einige Daten ändert, signalisiert er dem Server, die geänderten Daten neu zu laden. Was wir herausgefunden haben, ist, dass wir Hibernate mitteilen müssen, dass die Daten gelöscht und dann neu geladen werden sollen. Ein Fetch/Merge mit der db macht den Job nicht - hauptsächlich in Bezug auf die Objekte, die mehrere Ebenen in der Hierarchie sind.

Irgendwelche Gedanken darüber, ob irgendetwas grundsätzlich falsch mit diesem Design ist oder ob jemand dies tut und mehr Glück beim Arbeiten mit Hibernate beim Reload hatte.

Danke, Chris

Antwort

10

Eine Hibernate-Sitzung lädt alle Daten, die sie aus der DB liest, in den so genannten First-Level-Cache. Sobald eine Zeile aus der DB geladen ist, werden alle nachfolgenden Abrufe für eine Zeile mit demselben PK die Daten aus diesem Cache zurückgeben. Darüber hinaus referenzieren Hibernate gaurentees Gleichheit für Objekte mit der gleichen PK in einer einzigen Sitzung.

Soweit ich weiß, schließt Ihre schreibgeschützte Serveranwendung niemals ihre Hibernate-Sitzung. Wenn die DB von der Lese-Schreib-Anwendung aktualisiert wird, ist die Sitzung auf dem Nur-Lese-Server daher über die Änderung nicht informiert. Effektiv lädt Ihre schreibgeschützte Anwendung eine speicherinterne Kopie der Datenbank und verwendet diese Kopie, die zu gegebener Zeit veraltet wird.

Die einfachste und beste Vorgehensweise, die ich vorschlagen kann, ist das Schließen und Öffnen von Sitzungen nach Bedarf. Dies umgeht das ganze Problem. Hibernate Sessions sollen ein Fenster für eine kurzlebige Interaktion mit der DB sein. Ich stimme zu, dass es einen Leistungsgewinn gibt, wenn das Objekt-Diagramm nicht immer wieder neu geladen wird; aber du musst es messen und dich davon überzeugen, dass es die Mühe wert ist.

Eine weitere Option besteht darin, die Sitzung regelmäßig zu schließen und erneut zu öffnen. Dadurch wird sichergestellt, dass die schreibgeschützte Anwendung mit Daten arbeitet, die nicht älter als ein bestimmtes Zeitintervall sind. Aber es gibt definitiv ein Fenster, in dem die schreibgeschützte Anwendung mit veralteten Daten arbeitet (obwohl das Design garantiert, dass es letztendlich die aktuellen Daten erhält). Dies könnte in vielen Anwendungen zulässig sein - Sie müssen Ihre Situation bewerten.

Die dritte Option besteht darin, eine Second-Level-Cache Implementierung zu verwenden und kurzlebige Sitzungen zu verwenden. Es gibt verschiedene Caching-Pakete, die mit Hibernate mit relativen Vor- und Nachteilen arbeiten.

+0

JPA verwenden, und @PersistenceContext die EntityManager zu bekommen - aber es scheint, dass wir @PersistenceUnit für eine EntityManagerFactory benötigen und die Daten zu aktualisieren, haben wir einen neuen EntityManager bekommen. Hört sich gut an - aber auf die schwerste Art, Dinge auf den neuesten Stand zu bringen, aber wenn das die Leute machen ... –

3

Chris, ich bin ein wenig über Ihren persönlichen Umständen verwirrt. Wenn ich das richtig verstehe, hast du sowohl eine Web-App (lesen/schreiben) als auch eine Standalone-Anwendung (schreibgeschützt?) Mit Hibernate auf eine freigegebene Datenbank zugreifen können. Die Änderungen, die Sie mit der Web-App vornehmen, sind für die eigenständige App nicht sichtbar. Ist das richtig?

Wenn ja, haben Sie überlegt, eine andere Cache-Implementierung der zweiten Ebene zu verwenden? Ich frage mich, ob Sie möglicherweise einen geclusterten Cache verwenden können, der sowohl von der Webanwendung als auch von der eigenständigen Anwendung gemeinsam genutzt wird. Ich glaube, dass SwarmCache, das in Hibernate integriert ist, dies erlauben wird, aber ich habe es selbst nicht versucht.

Im Allgemeinen sollten Sie jedoch wissen, dass der Inhalt eines bestimmten Caches niemals Aktivitäten anderer Anwendungen erkennen wird (deshalb empfehle ich, dass beide Apps einen Cache teilen). Viel Glück!

2

Aus meiner Sicht sollten Sie Ihren Unterstreichungs-Ruhezustand-Cache auf den ändern, der den Cluster-Modus unterstützt. Es könnte ein JBoss Cache oder ein Swarm Cache sein. Der erste unterstützt die Datensynchronisation (Replikation und Invalidierung) besser und unterstützt auch JTA.

Dann können Sie die Cache-Synchronisation zwischen Webapp und Server konfigurieren. Überprüfen Sie auch die Isolationsstufe, wenn Sie JBoss Cache verwenden. Ich glaube, Sie sollten READ_COMMITTED Modus verwenden, wenn Sie neue Daten auf einem Server aus derselben Sitzung abrufen möchten.

1

Die am häufigsten verwendete Methode ist eine Container-Managed Entity Manager, so dass zwei oder mehr Anwendungen im selben Container (dh Glassfish, Tomcat, Websphere) die gleichen Caches teilen können. Aber wenn Sie keinen Anwendungscontainer verwenden, weil Sie Play! zum Beispiel, dann würde ich einige Webservices in der primären Anwendung bauen, um konsistent im Cache zu lesen/schreiben.

Ich denke, mit veralteten Daten ist eine offene Tür für eine Katastrophe. Genau wie Singletons werden Multitons, schreibgeschützte Anwendungen sind oft eine schreiben manchmal.

Gürtel und Hosenträger :)

Verwandte Themen