Estoy intentando crear una solución basada en Spring para ejecutar un lote de consultas SQL en el servidor MySQL 5.5. Por "consulta" me refiero a cualquier instrucción SQL que compila, por lo que el trabajo por lotes SQL puede contener, por ejemplo, varias instrucciones CREATE TABLE, DELETE y luego INSERT.Spring TransactionManager - commit no funciona
Estoy usando Spring Batch para este fin.
Tengo transactionManager
configurado de la siguiente manera.
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
y 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>
Mi clase DAO tiene el método configurado con
@Transactional(propagation = Propagation.REQUIRES_NEW)
y el bucle I sobre una colección de las sentencias SQL llamando al método con las sentencias SQL un momento. El procesamiento en el interior del método es tan simple como:
simpleJdbcTemplate.getJdbcOperations().execute(sql);
que esperaba que cuando el método DAO completa, me gustaría ver los resultados en la base de datos. Sin embargo, parece que solo cuando la ejecución del trabajo de Spring finaliza los resultados están disponibles en la base de datos.
Se ha intentado realizar la confirmación dentro de mi método 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");
}
I depurado el código de primavera y vi que la confirmación que llamo desde mi método DAO es ejecutado por TransactionTemplate (el flujo llegue a la línea this.transactionManager.commit(status);
y pasa sin excepciones)
Agradecería cualquier consejo sobre lo que se debe hacer para hacer que el método DAO se confirme en cada llamada (confirmación después de cada instrucción SQL que ejecuta).
@Transactional annotation se encarga de comprometerse. En su código, no necesita referencia al administrador de transacciones y supongo que debe realizar el cambio explícitamente. – ch4nd4n