Spring ist ein großartiges Framework für die Injektion von Abhängigkeiten und wird mit einer Vielzahl von Hilfsklassen und Dienstprogrammen für alle möglichen Dinge geliefert. Hibernate ist ein Persistenzdienst mit vielen nützlichen Funktionen, der relativ einfach zu verwenden ist. Die Konfiguration der beiden Frameworks ist nicht immer einfach. Sie zusammen zu konfigurieren ist manchmal schwierig und man kann leicht Fehler machen.
Dieser Blog behandelt ein Problem in einer Konfiguration, die ziemlich häufig vorkommt: Verwenden Sie Spring für die Transaktionsverwaltung auf einem JTA-Anbieter und verwenden Sie Hibernate für die Persistenz. Die Transaktionsabgrenzung ist mit Spring einfach und deklarativ. Das Problem ist, dass Hibernate manchmal die aktuelle Transaktion erkennen muss und dies konfiguriert werden muss. Dies führt zu schwer zu erkennenden Fehlern in Anwendungen, die auf Auto-Flushing angewiesen sind.
Auto Flushing
Auto Flushing ist eine Funktion von Hibernate, die den In-Memory-Status mit dem Datenbankstatus synchronisiert, wenn eine Abfrage ausgeführt wird. Normalerweise synchronisiert Hibernate den In-Memory-Status und den Datenbankstatus nur, wenn die Sitzung geleert wird. Bei Spring kann dies so konfiguriert werden, dass es beim Commit der Transaktion geschieht. Dies kann zu unerwartetem Verhalten führen. Sehen Sie sich den folgenden Code an
Um Hibernate direkt zu konfigurieren, verwenden Sie die Eigenschaften hibernate.transaction.manager_lookup_class und hibernate.transaction.factory_class. Diese Eigenschaften würden von Hibernate zum Starten von Transaktionen verwendet werden, aber wir starten keine Transaktionen über Hibernate, sondern erkennen sie nur.
Um Hibernate über Spring zu konfigurieren, injizieren Sie einen JtaTransactionManager in die LocalSessionFactoryBean. Je nach der spezifischen Version von Spring, die Sie verwenden, müssen weitere Einstellungen geändert werden.
Fazit
Die Entwicklung mit leistungsstarken Frameworks wie Spring und Hibernate macht viele Aufgaben einfach. Es ist von großer Bedeutung, dass die Frameworks richtig konfiguriert sind, insbesondere wenn sie zusammenarbeiten müssen. Ich hoffe, dass dieser Blog Ihnen hilft, einen kleinen Fehler in Ihrer Konfiguration zu entdecken, der zu schwerwiegenden Problemen führen könnte.
public void transactionInterceptedMethod() {
Person p = new Person("Maarten");
personDao.save(p);
Liste Personen = personDao.findAll();
}
Wird die neue Person auf der Liste der Personen stehen? Ich denke, jeder würde das vermuten. In der Tat hängt dies stark davon ab, wie Spring und Hibernate konfiguriert sind.
- Das Personenobjekt wird nicht sofort in die Datenbank eingefügt, wenn es Hibernate angeboten wird. Es wird im Speicher gehalten, bis die Sitzung geleert wird. (Es gibt Ausnahmen, aber dies ist die allgemeine Regel).
- Die findAll-Methode sucht in der Datenbank in derselben Transaktion wie die, die zum Einfügen des Personenobjekts verwendet wird. Dennoch findet sie die neue Person nur, wenn sie in derselben Transaktion vor der Abfrage in die Datenbank eingefügt wurde.
- Spring wird die Transaktion festschreiben und Hibernate anweisen, die aktuelle Sitzung erst am Ende der Methode zu löschen.
Verfasst von
Maarten Winkels
Contact
Let’s discuss how we can support your journey.