Bei einem Kunden verwenden wir jetzt Dateien und Datenquellen zusammen. Wir möchten, dass die Schreibvorgänge in die Datenbank und die Dateien in einer einzigen Transaktion erfolgen. Wir wollen dies, weil die Dateien die Datenbankdaten für Legacy-Anwendungen darstellen. Da es keine verteilte Transaktions-API für Dateien gibt, die mit JTA(Java Transaction API) kompatibel ist, mussten wir eine Lösung finden, um dies zu implementieren. Dieser Beitrag beschreibt die (großen) Schritte, die wir unternommen haben, und die Lösung, die wir gefunden haben. Natürlich können Sie die Schritte auch überspringen und direkt zur Lösung gehen ;-)
Der Schauplatz:
- Dateien, die sich in einem Versionsverwaltungssystem befinden
- eine relationale Datenbank
- Hibernate für das Mapping
- Feder für die Verkabelung
- Ein Objektmodell mit Organisation an der Wurzel des Objektbaums
- Eine Datei, die die Organisation so darstellen muss, wie sie in der Datenbank aus Gründen der Altlasten vorhanden ist
- JBoss Anwendungsserver
- Java 5
- Maven 2 für die Erstellung
Der Prozess: Zunächst haben wir uns überlegt, wie wir die Anforderung erfüllen können, dass die Datei den Zustand der Datenbank darstellt. Das erste, was mir einfiel, war die Verwendung des Interceptors, den Sie für Hibernate definieren können. Mein erster Versuch war, die postFlush-Methode zu verwenden. Die Überlegung dahinter war, dass, wenn der Flush in Ordnung ist, auch die Transaktion in Ordnung sein wird. Diese Methode wird jedes Mal nach dem Flushen der Daten in die Datenbank aufgerufen. Alle Objekte in der Hibernate-Sitzung werden als Iterator übergeben. Wir brauchen eine bestimmte Wurzel eines Objektbaums. Diese Klasse wird Organisation genannt. Wir brauchen diese Klasse, um eine Datei zu schreiben, die diese Organisation darstellt. Dies war jedoch sehr leistungsintensiv, da die Datei auch geschrieben wurde, wenn nichts aktualisiert wurde. Die Datei befindet sich im SCM, das die Datei sperrt, wenn wir sie aktualisieren wollen, und die Datei wird von vielen Legacy-Systemen verwendet, so dass dies keine Option war. Die onFlushDirty- und onSave-Methoden waren ebenfalls keine Option, da diese nur die Objekte abrufen, die geändert wurden, und wir das Objekt Organisation benötigen. Wenn also ein Objekt im Organisationsbaum geändert wurde, erhielten wir nur dieses Objekt. (Es bedurfte einiger Fehlersuche, bis wir dies tatsächlich herausfanden, da unsere Tests immer das Objekt Organisation selbst änderten.) Der nächste Schritt bestand darin, unsere eigene XAResource zu implementieren, die Dateien unter Verwendung des Apache Commons Transaction file package verarbeiten konnte. Nachdem wir etwas mehr gelesen hatten, stießen wir auf eine weitere Option, die wir jetzt mit Erfolg verwenden. Die Lösung: Nutzen Sie: Synchronisierung. Eine Synchronisierung kann bei einer Transaktion registriert werden und wird dann vor und nach einer Transaktion aufgerufen, um zu "synchronisieren". Dies hatte einen großen Vorteil: Bei der Suche nach einer Lösung haben wir uns viel mit Transaktionen beschäftigt. Das Schlimme daran war, dass wir beim Testen keine JTA-Transaktion, sondern eine Hibernate-Transaktion hatten. Die Transaktionsschnittstellen von JTA und Hibernate sind unterschiedlich. Aber eines der Dinge, die übereinstimmen, ist die Verwendung der Synchronisierung. Beide Transaktionsschnittstellen verwenden die gleiche Schnittstelle. Wir haben einen Wrapper für die beiden Transaktionsarten erstellt und verwenden diesen in unserem Code, um die Synchronisierung in einer Hibernate- oder JTA-Transaktion (die wir mit Spring erhalten) zu registrieren. Die Logik lautet nun: Beim Schreiben/Aktualisieren der Datenbank (im Code) rufen Sie das für die Datei und die Transaktion zuständige Objekt innerhalb der Transaktion auf. Dadurch wird die Datei unter Verwendung von SCM für die Versionierung geschrieben und die Synchronisierungsimplementierung registriert, die die Methode afterCompletion implementiert, um zu prüfen, ob die Transaktion zurückgesetzt wird oder nicht. Wenn die Transaktion zurückgenommen wird, wird auch die Aktualisierung der Datei mithilfe von SCM zurückgenommen. Da das Schreiben der Datei innerhalb der Transaktion erfolgt, wird die Transaktion zurückgerollt, wenn etwas nicht stimmt, und umgekehrt funktioniert es dank der Synchronisierung. Es sind wahrscheinlich auch andere Lösungen möglich, aber diese hier entspricht unseren Anforderungen und mir gefällt, dass die Synchronisierungsschnittstelle sowohl von Hibernate als auch von JTA unterstützt wird. Haftungsausschluss: Wenn Sie sich über die Schreibweise von Organisation wundern. Lesen Sie dies;-)
Verfasst von
Meindert Deen
Unsere Ideen
Weitere Blogs
Contact



