Für unser Projekt verwenden wir Hibernate. Die Anwendung, die wir erstellen, liest Workitems aus der Datenbank, verarbeitet sie (Validierung) und schreibt die Ergebnisse zurück in die Datenbank; eine typische Datenverarbeitungsanwendung. Optimal wäre ein Streaming-Prozess, bei dem ein gigantischer Select verwendet wird, um Millionen von Zeilen abzurufen und jede Zeile in einer Transaktion zu verarbeiten (die Verarbeitung einer Zeile führt zu mehreren DML-Anweisungen). Nun gibt es technische Hindernisse bei der Implementierung der Anwendung auf diese Weise. Das RDBMS sollte in der Lage sein, Millionen von kurzen Transaktionen zu verarbeiten, während die lange Transaktion, die die Zeilen liest, am Leben erhalten wird. Oracle kann dies aufgrund seiner Lesekonsistenzfunktionalität nicht bewältigen. Nach einiger Zeit führt ein
Der ProofOfConcept... widerlegt! Wir erwarteten einige Verbesserungen durch den Einsatz von Ibatis:
- Weniger Code - Keine Umgehung der Session von Hibernate mehr.
- Weniger SQL - Die meisten der Abfragen sind SQL-Abfragen, deren Ergebnisse von Hibernate interpretiert werden. Das liegt daran, dass sie Abfragehinweise und Konstrukte enthalten, die nicht einfach durch HQL oder Kriterien wiedergegeben werden können. Dies führt zu einer Menge Doppelarbeit, da einige logische Konstrukte (Joins, Einschränkungen) in mehreren Abfragen verwendet werden. Ibatis ermöglicht die gemeinsame Nutzung von Anweisungsfragmenten.
Wir haben damit begonnen, eine Einfügeanweisung für eines der Objekte zu definieren. Wir verwenden Sequenzen, um den Primärschlüssel in der Datenbank auszufüllen. In Hibernate verwenden wir den HiLoSequenceGenerator, um die Datenbank zu entlasten, wenn wir eine große Menge an Daten einfügen. Wie würden wir dies in Ibatis implementieren? Nun, Ibatis verfügt über selectKey-Eigenschaften, um den Primärschlüssel eines neu eingefügten Objekts zu generieren. Der hi/lo-Mechanismus ist eine sehr einfache Erweiterung, die auf jeden Schlüsselgenerierungsmechanismus angewendet werden kann. Er wendet einfach eine Lineair-Transformation auf den generierten Schlüssel an, was zu einem ganzen Bündel von Schlüsseln führt. Wie können wir dies in Ibatis implementieren? Nun, wir könnten einfach das SelectKeyStatement erweitern. Oke erweitern, aber dann müssen wir in Ibatis unsere eigene Implementierung verwenden und nicht die normale SelectKeyStatement-Implementierung. Wo wird das Objekt also erstellt? Wird das Factory-Muster verwendet? Gibt es ein Plug-in oder einen Erweiterungspunkt? Nein! Das SelectKeyStatement wird direkt beim Lesen der Konfigurationsdatei instanziiert. Das ist ein wenig enttäuschend! Na ja, vielleicht denken wir hier zu sehr an Hibernate. Wir könnten hi/lo einfach vergessen, unsere Sequenzen auf genau den nächsten Wert zurücksetzen, den wir brauchen, und sie dann bei jeder neuen Eingabe verwenden. Wenn wir schon dabei sind, welche Erweiterungspunkte hat Ibatis? Nun, wenn wir uns die Quellen ansehen, finden wir... drei Erweiterungen< im Client! Die Engine verfügt über keine Erweiterungen. Das scheint ein großer Nachteil zu sein. Meiner Erfahrung nach sind ORM-Lösungen nie zu 100 % passend. Es gibt immer diese eine Tabelle/Objekt-Zuordnung, die ein paar Anpassungen erfordert, damit sie richtig funktioniert. Ein Framework, das so begrenzte Möglichkeiten für Erweiterungen bietet, macht sich selbst unbrauchbar. Oke, lassen Sie uns nicht so schnell aufgeben. Wir können immer noch versuchen, wie weit wir mit Ibatis in seiner jetzigen Form kommen können. Wir müssen nur eine Handvoll verschiedener SQL-Abfragen in der Datenbank ausführen und das Ergebnis jeder Abfrage sollte auf einige wenige Objekte abgebildet werden. Das sollte möglich sein. Lassen Sie uns einen Test schreiben, der eine Sequenz verwendet und dann ein Objekt einfügt. Wir verwenden HSQLDB für unsere Tests. Es ist schnell, einfach zu bedienen und kann auf allen Entwickler- und Testplattformen ausgeführt werden. Jetzt müssen wir also eine "insert"-Anweisung in unserer SQL-Map-Konfiguration erstellen. Die Einfügeanweisung ist einfach; es handelt sich um Standard-SQL: [sql]INSERT INTO TABLE (COL1, COL2, COL3, ...) VALUES (?, ?, ?, ?, ...)[/sql] Dies funktioniert auf jedem gesetzestreuen Datenbanksystem. Nun zu der "selectKey"-Anweisung... Bei Oracle sieht sie etwa so aus [sql]SELECT SEQUENCE.NEXTVAL FROM DUAL[/sql] Bei HSQLDB ist das ziemlich vage. Ein Wert aus einer Sequenz kann nur in einer normalen "SELECT"-Anweisung ausgewählt werden. Die Anweisung sollte auf einer Tabelle (oder einer tabellenähnlichen Struktur) ausgeführt werden, wie in der "FROM"-Klausel angegeben. Die Anweisung kann auch eine "WHERE"-Klausel mit Einschränkungen enthalten. Für jede Zeile in der Ergebnismenge, die sich aus der Anweisung ergibt, wird dann eine Sequenznummer ausgewählt. Die folgende Anweisung führt also zu einer Sequenznummer für jede Zeile in TABLE. [sql]SELECT NEXTVALUE FOR SEQUENCE FROM TABLE[/sql] Um nur eine einzige Sequenznummer abzurufen, sollte die Anweisung genau ein Ergebnis liefern. Die Tabelle sollte also nur eine Zeile enthalten. Genau so arbeitet der HSQLDialect von Hibernate mit Sequenzen:
- Sie erstellt eine Sequenz
- Es erstellt eine Tabelle
- Er fügt einen einzelnen Datensatz in die Tabelle
- Es verwendet die Tabelle, um die nächsten Werte für die Sequenz auszuwählen
Das ist eine Menge Arbeit. Das Hauptproblem ist jedoch nicht die Arbeit, sondern die Tatsache, dass HSQLDB, das Test-RDBMS, Sequenzen auf eine völlig andere Weise behandelt als Oracle, das Produktions-RDBMS. Wie können wir nun Ibatis so konfigurieren, dass es auf einem anderen RDBMS läuft? Oh, das geht nicht. Ibatis kennt nur Anweisungen und nur eine einzige Version einer Anweisung, keine datenbankspezifischen Versionen. Umpf, eine weitere große Enttäuschung. Wir müssten also eine separate Version der SQL Map-Konfiguration zum Testen erstellen und damit den Zweck des Testens der DAO-Schicht unserer Anwendung zunichte machen. Die Tatsache, dass Hibernate über Dialekte verfügt, die ein- und ausgetauscht werden können, mag unser Urteilsvermögen trüben, aber wir glauben, dass dies die Testbarkeit einer Anwendung, die Ibatis für ihre DAO-Schicht verwendet, ernsthaft beeinträchtigt. Das Testen gegen Oracle ist sehr langsam und schwer auf allen Plattformen zu implementieren (wir müssten Oracle überall installieren). Fazit Nach einigen Stunden des Versuchs, von Hibernate zu Ibatis zu konvertieren, haben wir zwei große Enttäuschungen festgestellt: geringe Erweiterbarkeit und geringe Testbarkeit. Wir konnten nicht überprüfen, ob Ibatis die Probleme lösen würde, die wir derzeit haben. Auch die erwarteten Verbesserungen konnten wir nicht überprüfen. Also kehren wir zu unserem guten alten goldenen Hammer zurück: Hibernate! Vielleicht gibt es noch andere ORM-Frameworks, die wir untersuchen könnten. Es gibt JDO und TopLink, aber diese fortschrittlichen Lösungen werden wahrscheinlich das gleiche Problem haben wie Hibernate: ungenutzte Funktionen, die wir umgehen müssen, damit alles funktioniert. Wir könnten natürlich unser eigenes Framework mit genau den Funktionen erfinden, die wir für diese Anwendung benötigen, aber... ähm... wäre das dann noch ein Framework? Vielleicht zeigt unsere Erfahrung, dass Hibernate so gut ist , wie es nur geht Maarten Winkels Machiel Groeneveld
Verfasst von
Maarten Winkels
Unsere Ideen
Weitere Blogs
Contact



