Spring JPA Read-Write-splitting - Transaktionen verwenden Sie die datasource schreiben
Ich habe eine Anwendung, die verwendet Hibernate/JPA, mit Feder und Jersey. In meinem Anwendungskontext ich die Datenquelle definieren Sie ein entity-manager-factory, set transaction manager mit, dass die entity Manager factory, und haben verschiedene service-Methoden annotiert werden, mit der transactional-annotation, also ich habe auch das tx:annotation-driven definition zu Draht in meinem Transaktions-manager, wo Sie benötigt wird. Dieses setup funktioniert Super, ich habe in der Lage zu Lesen und zu schreiben, einfach nur gut. Ich möchte, um zu einer DB eingerichtet, wo ich ein Master mit mehreren slaves (MySQL). Also ich möchte, dass alle Methoden, annotiert mit Transaktions -, um eine Datenquelle verwenden, zeigen auf der master-db-server, und alle anderen, eine Verbindung zu verwenden-pool der Sklaven.
Habe ich versucht, die Schaffung von zwei unterschiedlichen Datenquellen, mit zwei verschiedenen entity-manager in den Fabriken und in zwei verschiedenen persistenten Einheiten - hässlich, gelinde gesagt. Ich habe versucht, eine MySQL-Proxy, aber wir hatten mehr Probleme mit, die wir dann brauchen. Die Verbindungs-pooling verarbeitet wird, in der servlet-container schon. Könnte ich implementieren, etwas in Tomcat liest die Transaktion und leitet es an die richtigen Datenbank-server, oder gibt es eine Möglichkeit, ich könnte alle diese Methoden annotiert werden, mit der transactional-annotation zu verwenden, eine bestimmte datasource?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Hier ist, was ich am Ende machen, und es funktionierte ganz gut. Der entity-manager kann nur eine Bohne, die als Datenquelle. Also, was ich tun musste, war die Erstellung einer bean, die geroutet zwischen den beiden, wo nötig. Dass man ben ist die, die ich für die JPA-entity-manager.
Ich ein setup von zwei unterschiedlichen Datenquellen in tomcat. In der server.xml ich habe zwei Ressourcen (Datenquellen).
Haben, könnten Sie den Datenbank-Tabellen auf dem gleichen server, in dem Fall die ip-Adressen oder domain wäre die gleiche, nur verschiedene dbs - Sie bekommen den jist.
Ich dann noch ein link in der Ressource context.xml Datei in tomcat verwiesen diese auf die Ressourcen.
Diese resource-links sind das, was Frühling liest in der Anwendung Kontext.
In der Anwendung Kontext-ich habe eine bean-definition für jede Ressource, link und fügte hinzu, eine zusätzliche bean-definition, die sich auf eine Datasource-Router bean, die ich erstellt, nimmt in einer Karte (enum), der die beiden zuvor erstellten beans (bean-definition).
Den entity-manager-bean-definition dann auf die dataSource-bean.
Definierte ich einige Eigenschaften in einer properties-Datei, aber Sie können ersetzen Sie die $ {} - Werte mit Ihren eigenen Werten. So, jetzt habe ich eine bean, die mit zwei anderen Bohnen, dass sind meine zwei Datenquellen. Die eine Bohne ist die eine, die ich für JPA. Es ist blind für jede routing geschieht.
So, jetzt die routing-bean.
Die überschriebene Methode wird aufgerufen, indem der entity-manager, um zu bestimmen, die Quelle der Daten grundsätzlich. Die DatasourceProvider hat einen lokalen thread (thread-sichere) Eigenschaft eine getter-und setter-Methode sowie die eindeutige Datenquelle Methode für die Reinigung.
Habe ich eine generische DAO-Implementierung mit den Methoden, die ich verwenden, um die Behandlung verschiedener routine JPA anrufen (getReference -, bestehen, createNamedQUery & getResultList, etc.). Bevor er den Anruf macht, um den entityManager zu tun, was es tun muss ich die DatasourceProvider datasource zu Lesen oder zu schreiben. Die Methode kann damit umgehen-Wert weitergegeben werden, als auch, um es ein wenig mehr Dynamik. Hier ist ein Beispiel-Methode.
Den AvailableDataSources ist ein enum mit LESEN oder zu SCHREIBEN, der auf die entsprechende Datenquelle. Sie können sehen, dass in der Karte definiert, die in meinem bean auf den Anwendungskontext.
Habe ich die gleiche Art von Notwendigkeit : die route die Verbindung zwischen readonly und writeonly-Datenbank mit einer klassischen MASTER /SLAVE-Skalierung liest.
Habe ich am Ende eine schlanke Lösung, mit der AbstractRoutingDataSource Basisklasse von Frühling. Es erlaubt, Sie zu injizieren einer Datenquelle, die Routen zu mehreren datasources basiert auf einigen Voraussetzungen, die Sie schreiben.
Und mein router einfach sieht wie folgt aus :
Ich finde das ganz elegant, aber das problem ist hier, dass der Frühling scheint sich um die Transaktion, readonly, nach Injektion der datasource, so funktioniert es nicht. Meine einfache test ist zu überprüfen das Ergebnis der TransactionSynchronizationManager.isCurrentTransactionReadOnly() in meinem readonly Methoden (es ist wahr), und in der determineCurrentLookupKey () - Methode, wo es falsch ist auf den gleichen Anruf.
Wenn man Ideen hat... wie auch immer Sie sich stützen könnte, den test auf etwas anderes als TransactionSynchronizationManager und dieser wird funktionieren.
Hoffe, das hilft,
Christophe
-->