2016-05-18 16 views
0

Ich versuche, Spring Transaction Management in meiner neuen Spring Boot + MyBatis-Anwendung arbeiten zu lassen.Spring Transaction Management funktioniert nicht mit Spring Boot + MyBatis?

Bis jetzt habe ich es geschafft, alles mit minimalen Problemen arbeiten zu lassen - es wird nur die @Transactional Annotation richtig funktionieren. Derzeit werden alle Anweisungen sofort übernommen, unabhängig davon, ob die Methode mit Anmerkungen versehen ist oder nicht.

Spring Boot macht so viel von der Standardkonfiguration für Sie, dass es schwierig ist, das fehlende Glied zu finden.

My build.gradle enthält die folgenden Abhängigkeiten:

compile("org.springframework.boot:spring-boot-starter-amqp") 
compile("org.mybatis.spring.boot:mybatis-spring-boot-starter:1.0.0") 
compile("mysql:mysql-connector-java:5.1.38") 

My application.properties enthält die folgende Datenquelle Konfiguration:

spring.datasource.driver-class-name=com.mysql.jdbc.Driver 
spring.datasource.url=jdbc:mysql://localhost:3306/my_db 
spring.datasource.username=my_user 
spring.datasource.password=my_pass 

Ein einfaches Beispiel für ein Verfahren in einer Bean, das wirkt, wird nicht so wie erwartet ist, folgt:

@Transactional 
public void performTransactionTest() throws Exception { 

    Person person = new Person(); 
    person.setPersonId(123); 
    personMapper.insert(person); 

    throw new Exception("This should force a rollback!"); 

} 

Die Ausnahme wird ausgelöst, aber der Datensatz wurde bereits eingefügt.

Es gibt im Grunde genommen keine Dokumentation zur Transaktionskonfiguration für Spring Boot AND MyBatis zusammen, aber soweit ich weiß, sollte es sich größtenteils verkabeln, wie es manuell in einer Spring + MyBatis-Anwendung gemacht würde und wo es nicht funktioniert. t - wir können es weiter konfigurieren. Mit dieser sagte ich die folgenden Konfigurationen in meinem applicationContext.xml ohne Glück versucht:

<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" /> 

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <property name="dataSource" ref="dataSource" /> 
</bean> 

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
</bean> 

kann ich bestätigen, dass auch ohne eine der oben genannten Konfigurationen eine DataSourceTransactionManager mit derselben Datasource konfiguriert ist, dass die Mybatis Mapper SqlSession verwendet.

Jede Hilfe oder Ideen, die mich in die richtige Richtung drücken könnten, würde sehr geschätzt werden. Wenn Sie weitere Informationen benötigen, stelle ich Ihnen diese gerne zur Verfügung!

Vielen Dank im Voraus!

Xandel

+0

Das Annotieren von privaten Methoden ist nicht gut. siehe http://stackoverflow.com/q/7085271/217324 –

+0

Haben Sie die Frage bearbeitet - ich kann bestätigen, dass das Problem mit einer öffentlichen Methode weiterhin besteht. – Xandel

+0

Auch geprüfte Ausnahmen verursachen standardmäßig kein Rollback. –

Antwort

0

Also habe ich es funktioniert, indem die Klassendefinition mit @Transactional anstelle der Methodendefinition mit Anmerkungen versehen.

Ich bin nicht sicher, ob dies gängige Praxis ist. Die Frühjahr-Boot-Transaktionsmanagement-Dokumentation macht es nicht wie dieser here aber die Mybatis Federprobe hat in ihrer Dokumentation es auf diese Weise tun here ...

Wenn jemand weitere Informationen hat, die dies erklären könnte ich glücklich, dass die Antwort markieren wird als der richtige.

Für jetzt jedoch ist mein Problem gelöst.

EDIT

Zurückkommend auf dieses Problem Monat später habe ich endlich auf den Grund zu bekommen. Es gab hier zwei Hauptprobleme.

  1. Wie Kazuki richtig erwähnt, müssen Sie ausdrücklich erklären, dass Rollbacks für geprüfte Ausnahmen mit der @Transactional(rollbackFor = Exception.class) Anmerkung passieren müssen.

  2. "Transaktionsgrenzen werden nur erstellt, wenn ordnungsgemäß annotierte Methoden über einen Spring-Proxy aufgerufen werden. Dies bedeutet, dass Sie Ihre annotierte Methode direkt über eine @Autowired-Bean aufrufen müssen oder die Transaktion wird niemals gestartet." (Hinweis auf diese Quelle unten)

In meinem Beispielcode wurde ich this.performTransactionTest() aus der gleichen Klasse aufrufen. Auf diese Weise wird die Transaktion ignoriert. Wenn ich es stattdessen über eine verdrahtete Referenz zu meiner Klasse wie myAutoWiredBean.performTransactionTest() anrufe, funktioniert alles wie erwartet. Dies erklärt auch, warum anscheinend nur die Annotation auf Klassenebene funktioniert hat, aber das liegt daran, dass jede aufgerufene Methode von einer verdrahteten Bean referenziert worden wäre.

Zwei Artikel, die MAJOR Unterstützung für das Verständnis der feineren Details des Transaktionsmanagements von Spring waren, sind hier. Ein großes Dankeschön an die Autoren Nitin Prabhu und Tim Mattison.

https://dzone.com/articles/spring-transaction-management

http://blog.timmattison.com/archives/2012/04/19/tips-for-debugging-springs-transactional-annotation/

Ich hoffe, das jemand hilft!

0

Ein Standardverhalten von Spring Transaction Management ist festgeschrieben, wenn eine Überprüfungsausnahme aufgetreten ist (Ausnahme oder Unterklasse). Wenn Sie eine Transaktion zurücksetzen möchten, können Sie eine Ausnahme für die Ausnahme auslösen (RuntimeException oder Unterklasse). Auch @Transactional (rollbackFor = Exception.class) ist das gleiche Ergebnis.

Bitte versuchen Sie es.

Details siehe http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#transaction-declarative-rolling-back

Dank.

Verwandte Themen