Sto provando a creare una soluzione basata su Spring per eseguire batch di query SQL sul server MySQL 5.5. Per "query" intendo qualsiasi istruzione SQL che compila, quindi il lavoro batch SQL può contenere per esempio più istruzioni CREATE TABLE, DELETE e quindi INSERT.Spring TransactionManager - commit non funziona
Sto usando Spring Batch per questo scopo.
Ho transactionManager
configurato come segue.
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
e la 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>
La mia classe DAO ha il metodo configurato con
@Transactional(propagation = Propagation.REQUIRES_NEW)
e passante ho più di un insieme di istruzioni SQL chiamando il metodo con istruzione SQL un tempo. L'elaborazione all'interno del metodo è il più semplice:
simpleJdbcTemplate.getJdbcOperations().execute(sql);
Mi aspettavo che quando il metodo DAO completa, vorrei vedere i risultati nel DB. Tuttavia, sembra che solo quando l'esecuzione del lavoro Spring termina, i risultati diventano disponibili nel DB.
ho cercato di fare il commit all'interno del mio metodo DAO:
@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");
}
ho il debug del codice primavera e ho visto che l'impegno che io chiamo dal mio metodo DAO viene eseguito dal TransactionTemplate (il flusso raggiunge la linea this.transactionManager.commit(status);
e passa senza eccezioni)
Apprezzerei qualsiasi consiglio su cosa dovrebbe essere fatto per rendere il metodo DAO da impegnare su ogni chiamata (commit dopo ogni istruzione SQL eseguita).
@ L'annotazione di transazione si occupa dell'impegno. Nel tuo codice non è necessario fare riferimento al gestore delle transazioni e commettere esplicitamente la modifica, suppongo. – ch4nd4n