Frühjahr: HibernateTransactionManager Umgang mit mehreren Datenquellen
In das folgende Stück code (Feder 3):
@Transactional("txManager")
public class DaoHolder {
@Transactional(value="txManager", readOnly=false, propagation=Propagation.REQUIRES_NEW, rollbackFor={Exception.class})
private void runTransactionalMethod() throws Exception {
dao1.insertRow();
dao2.insertRow();
//throw new Exception();
}
//...
}
- dao1 verwendet ein session-factory befestigt datasource1
- dao2 verwendet ein session-factory befestigt datasource2
- txManager ist ein HibernateTransactionManager mit der gleichen session factory als dao1
Den code oben funktioniert korrekt in einer transaktionalen Weise - insbesondere, wenn keine Ausnahme geworfen wird, die einzelnen dao-Betrieb wird verpflichtet (zu 2 verschiedene datasources). Wenn eine Ausnahme geworfen wird jedes dao-operation wird rückgängig gemacht.
Meine Frage ist: warum funktioniert es? Überall wo ich gelesen habe, ich habe gesagt, die Verwendung einer JtaTransactionManager beim Umgang mit mehreren Datenquellen. Ich würde lieber nicht verwenden JTA. Was könnten die Folgen sein wenn ich lassen Sie es unter einem HibernateTransactionManager?
Einige weitere details für den interessierten:
Jede Datenquelle definiert ist, etwa so:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="initialSize" value="${jdbc.initial_size}" />
<property name="maxActive" value="${jdbc.max_active}" />
</bean>
Jeder session factory ist definiert wie folgt:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
... multiple *.hbm.xml files here ...
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
</bean>
Des Transaktions-MANAGERS definiert, wie so:
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
Jede dao-Klasse extends HibernateDaoSupport und die Inhalte der insertRow-Methode ist mehr oder weniger wie so für dao1:
getHibernateTemplate().save(obj);
und für dao2:
getHibernateTemplate().merge(obj);
insertRow()
und Konfiguration von session-Fabriken, Transaktions-Managern, etc?Sicher, gerade Hinzugefügt 🙂
Sind Sie sicher, dass Ihre DAOs tatsächlich nutzen verschiedene Datenquellen? Es ist nicht klar, in der config die du gepostet.
Ja, ich bin mir 100% sicher. Nachdem der Vorgang abgeschlossen ist, habe ich eigentlich überprüfen der DBs für Ergebnisse, sodass für diese das problem zu sein, ich hätte zu schlechte Konfiguration UND schaut in die gleiche Datenbank. Die datasources sind zwei Postgres-DBs auf dem gleichen host.
Haben Sie versucht, Sie anzurufen, bündig an beiden Sitzungen vor dem werfen der exception?
InformationsquelleAutor machinery | 2012-01-02
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die Frage:
Ich verbrachte den letzten Tag den Umgang mit dieser genauen Frage: Warum Transaktionen zwischen den Datenquellen angezeigt, die Arbeit mit einem hibernate transaction manager?
Wie du, ich lese auch in mehreren Orten, die ich brauchte, um eine JtaTransactionManager...und es stellt sich heraus, Sie hatten Recht! Ich werde erklären:
Konfiguration:
Genau wie Sie begann ich mit 2 Daten-Quellen, 2-Sitzung in den Fabriken und in 1 HibernateTransactionManager.
Mein test-code sah auch sehr ähnlich wie bei Ihnen und ich könnte speichern von Objekten auf beide Datenbanken erfolgreich. Wenn ich manuell warf eine Ausnahme, weder speichern in der Datenbank. So schien es, die beiden wurden korrekt zurückgerollt. Jedoch wenn ich eingeschaltet hibernate debug-Protokollierung, konnte ich sehen, dass weder speichern lag tatsächlich an den Datenbanken, so gab es nichts zu rollback.
Das problem ist in der test, so werde ich Sie ändern Ihr test, um zu beweisen, dass die einzelne Transaktion-manager ist eigentlich nicht funktioniert!
Die Veränderung, die wir brauchen, wurde vorgeschlagen, durch JB Nizet am Jan 2:
Ein besserer test:
Ersten, fügen Sie eine flush-Funktion, die auf jedem Ihrer DAO. Dies ist, was mir aussieht:
Deine wird wahrscheinlich so Aussehen:
Nun, ändern Sie Ihren test zu Spülen jedes dao vor die Ausnahme:
Das Ergebnis:
Nur die datasource zugeordnet txManager wird ein Rollback ausgeführt. Das macht Sinn, weil txManager weiß nicht, über den anderen Datenquelle.
Zusammenfassung:
In meinem Fall, brauche ich nicht zu Zugriff auf 2 Datenbanken in einer Transaktion, separate Transaktionen ist in Ordnung. Also habe ich einfach definiert, eine zweite Transaktions-manager:
Und referenziert diese mit Namen in der Transactional-annotation, wo ich Zugriff auf die zweite Datenbank:
Ich können jetzt auch kommentiert Transaktionen für meine zweite Datenbank, aber ich kann immer noch nicht bekommen, Transaktionen über beide Datenbanken...es scheint, dass Sie benötigen, JtaTransactionManager.
In Ihrem ursprünglichen test, der flush nicht auftreten, bis nach der Ausnahme. Also die Datenbanken sind entweder einfügen & Begehen beide Zeilen sind erfolgreich oder scheitern, bevor jeder Treffer fügt der Datenbank. Der Punkt, der Transaktionen & rollbacks ist die undo-commit-Einsätze, die auf die Datenbank.
(Fortsetzung) Die Verwirrung ist, da hibernate nicht sofort senden Sie die Einsätze, um die Datenbank-wie man erwarten würde, wenn Sie wurden mit jdbc direkt. Eine Analogie ist, dass du geschrieben hast überprüfen, aber Sie haben nie ließ es in der E-mail...und so gibt es keine Notwendigkeit zu gehen, um die bank zu setzen eine stop-Zahlung auf. Zum test der bank stop-payment-system, mit dem wir eigentlich brauchen, um die drop-check in der post, das ist, was die Spülung zu tun.
Vielen Dank, Mann! Perfekte Erklärung. Hatte die gleiche situation mit den gleichen Fragen. Jetzt ist alles vollkommen klar!
InformationsquelleAutor Henry