Frühjahr TransactionManager - commit klappt nicht
Ich versuche zu erstellen, Spring-basierte Lösung für die Ausführung von batch von SQL-Abfragen auf MySQL-5.5-server.
Von "query", ich meine jede SQL-Anweisung kompiliert, so dass der SQL-batch-job kann enthalten beispielsweise mehrere TABELLE ERSTELLEN, LÖSCHEN und INSERT-Anweisungen.
Ich bin mit Spring Batch für diesen Zweck.
Habe ich transactionManager
wie folgt konfiguriert.
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
und die dataSource
:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${batch.jdbc.driver}" />
<property name="url" value="${batch.jdbc.url}" />
<property name="username" value="${batch.jdbc.user}" />
<property name="password" value="${batch.jdbc.password}" />
<property name="maxIdle" value="10" />
<property name="maxActive" value="100" />
<property name="maxWait" value="10000" />
<property name="validationQuery" value="select 1" />
<property name="testOnBorrow" value="false" />
<property name="testWhileIdle" value="true" />
<property name="timeBetweenEvictionRunsMillis" value="1200000" />
<property name="minEvictableIdleTimeMillis" value="1800000" />
<property name="numTestsPerEvictionRun" value="5" />
<property name="defaultAutoCommit" value="true" />
</bean>
Meiner DAO-Klasse hat die Methode konfiguriert mit
@Transactional(propagation = Propagation.REQUIRES_NEW)
- und I-Schleife über eine Sammlung von SQL-Anweisungen aufrufen der Methode mit einem einzigen SQL-Anweisung zu einem Zeitpunkt.
Die Verarbeitung innerhalb der Methode ist einfach:
simpleJdbcTemplate.getJdbcOperations().execute(sql);
Ich erwartet, dass, wenn die DAO-Methode abgeschlossen ist, würde ich die Ergebnisse in die DB.
Jedoch, wie es scheint, nur, wenn die Feder jobausführung abgeschlossen, die Ergebnisse werden in die DB.
Wollte ich die commit in meinem DAO-Methode:
@Transactional(propagation = Propagation.REQUIRES_NEW)
private void executeSingleQuery(String sql) {
PlatformTransactionManager transactionManager = (PlatformTransactionManager)context.getBean("transactionManager");
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(Propagation.REQUIRED.ordinal());
TransactionStatus status = transactionManager.getTransaction(def);
try {
//execute your business logic here
log.info("about to execute SQL query[" + sql + "]");
simpleJdbcTemplate.getJdbcOperations().execute(sql);
} catch (Exception e) {
log.info("SQL query was not committed due to exception and was marked for rollback");
transactionManager.rollback(status);
}
transactionManager.commit(status);
if (transactionManager.getTransaction(null).isRollbackOnly()
&& transactionManager.getTransaction(null).isCompleted()) {
log.info("SQL query commited!");
} else {
log.info("SQL query was not committed due to: 1) the transaction has been marked for rollback " +
"2) the transaction has not completed for some reason");
}
log.info("the query has completed");
}
Ich gedebuggt den Quellcode und sah, dass die commit-ich nenne aus meiner DAO-Methode wird ausgeführt, indem TransactionTemplate (der Fluss erreicht die Linie this.transactionManager.commit(status);
und geht ohne Ausnahmen)
Ich würde schätzen jede Beratung, was getan werden sollte, um die DAO-Methode zu verpflichten, bei jedem Anruf (commit nach jeder SQL-Anweisung ausgeführt wird).
InformationsquelleAutor aviad | 2012-04-10
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie proxy-private Methoden. also Die @Transactional-Sie haben hier keine Auswirkung hat. Ziehen Sie die Methode, um Ihre übergeordneten-Schnittstelle und es sollte funktionieren. Es sei denn, Sie haben die proxyTargetClass Einstellung aktiviert, die wird nicht empfohlen.
ziehen Sie die Methode, um die übergeordnete Schnittstelle der situation geholfen hat. Shukran! 🙂
InformationsquelleAutor MahdeTo
Wenn Sie rufen Sie Ihren
executeSingleQuery()
innerhalb der gleichen Klasse, die Sie nicht gehen über den proxy, so das transactional annotation wird keine Wirkung haben.Mischen Sie deklarative und programmatische Transaktionen, Vermutlich wollen Sie
REQUIRES_NEW
so könnte man entfernen, die sinnlos@Transactional
annotation und VerwendungPropagation.REQUIRES_NEW
bei der Einrichtung IhresDefaultTransactionDefinition
.Auch, möchten Sie vielleicht zu verschieben
transactionManager.commit(status)
innerhalb dertry
sperren, Ihren aktuellen code ein, rollt sich zurück, versucht dann ein commit, wenn einException
Auftritt.InformationsquelleAutor samlewis
Wir die
@Rollback(value = false)
Anmerkung, und dass das Problem Sie konfrontiert sind.InformationsquelleAutor John Harris