BATCH-970: leaving the 1.1 branch as it was - adding the optional transaction configuration to the new 2.0 version
This commit is contained in:
@@ -33,7 +33,6 @@ import org.springframework.batch.item.support.AbstractBufferedItemReaderItemStre
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
import org.springframework.jdbc.SQLWarningException;
|
||||
import org.springframework.jdbc.datasource.DataSourceUtils;
|
||||
import org.springframework.jdbc.core.PreparedStatementSetter;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.support.JdbcUtils;
|
||||
@@ -80,7 +79,13 @@ import org.springframework.util.ClassUtils;
|
||||
* transaction is rolled back, the current row can be moved back to the same row
|
||||
* number as it was on when commit was called.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* NOTE that the cursor is opened using a separate connection from the rest of the
|
||||
* processing in the step. This means that this reader also runs within its own
|
||||
* JDBC transaction.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Calling close on this {@link ItemStream} will cause all resources it is
|
||||
* currently using to be freed. (Connection, ResultSet, etc). It is then illegal
|
||||
@@ -134,9 +139,7 @@ public class JdbcCursorItemReader extends AbstractBufferedItemReaderItemStream i
|
||||
|
||||
private boolean driverSupportsAbsolute = false;
|
||||
|
||||
private boolean participateInExistingTransaction = false;
|
||||
|
||||
public JdbcCursorItemReader() {
|
||||
public JdbcCursorItemReader() {
|
||||
setName(ClassUtils.getShortName(JdbcCursorItemReader.class));
|
||||
}
|
||||
|
||||
@@ -173,13 +176,9 @@ public class JdbcCursorItemReader extends AbstractBufferedItemReaderItemStream i
|
||||
Assert.state(dataSource != null, "DataSource must not be null.");
|
||||
|
||||
try {
|
||||
if (participateInExistingTransaction) {
|
||||
this.con = DataSourceUtils.getConnection(dataSource);
|
||||
}
|
||||
else {
|
||||
this.con = dataSource.getConnection();
|
||||
}
|
||||
preparedStatement = this.con.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
|
||||
// Note: this is a connection that is separate from the current transaction
|
||||
this.con = dataSource.getConnection();
|
||||
preparedStatement = this.con.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
|
||||
ResultSet.HOLD_CURSORS_OVER_COMMIT);
|
||||
applyStatementSettings(preparedStatement);
|
||||
if (this.preparedStatementSetter != null) {
|
||||
@@ -387,19 +386,6 @@ public class JdbcCursorItemReader extends AbstractBufferedItemReaderItemStream i
|
||||
this.driverSupportsAbsolute = driverSupportsAbsolute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether the cursor should be opened as part of an existing transaction or if it
|
||||
* should be opened in its own transaction. The default is for the cursor to be opened in its
|
||||
* own transaction. If you set this flag to true then you should wrap the DataSource in a
|
||||
* {@link org.springframework.jdbc.datasource.SingleConnectionDataSource} to prevent the
|
||||
* connection from being closed after each commit.
|
||||
*
|
||||
* @param participateInExistingTransaction <code>false</code> by default
|
||||
*/
|
||||
public void setParticipateInExistingTransaction(boolean participateInExistingTransaction) {
|
||||
this.participateInExistingTransaction = participateInExistingTransaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the result set is in synch with the currentRow attribute. This is
|
||||
* important to ensure that the user hasn't modified the current row.
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
package org.springframework.batch.item.database;
|
||||
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.item.ItemStream;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.easymock.MockControl;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
|
||||
public class JdbcCursorItemReaderConfigTests extends TestCase {
|
||||
|
||||
/*
|
||||
* Should fail if trying to call getConnection() twice
|
||||
*/
|
||||
public void testUsesCurrentTransaction() throws Exception {
|
||||
//TODO:
|
||||
}
|
||||
|
||||
/*
|
||||
* Should not fail if trying to call getConnection() twice
|
||||
*/
|
||||
public void testUsesItsOwnTransaction() throws Exception {
|
||||
MockControl ctrlDataSource;
|
||||
DataSource mockDataSource;
|
||||
MockControl ctrlConnection;
|
||||
Connection mockConnection;
|
||||
MockControl ctrlPreparedStatement;
|
||||
PreparedStatement mockPreparedStatement;
|
||||
MockControl ctrlResultSet;
|
||||
ResultSet mockResultSet;
|
||||
|
||||
ctrlResultSet = MockControl.createControl(ResultSet.class);
|
||||
mockResultSet = (ResultSet) ctrlResultSet.getMock();
|
||||
|
||||
ctrlPreparedStatement = MockControl.createControl(PreparedStatement.class);
|
||||
mockPreparedStatement = (PreparedStatement) ctrlPreparedStatement.getMock();
|
||||
mockPreparedStatement.executeQuery();
|
||||
ctrlPreparedStatement.setReturnValue(mockResultSet);
|
||||
mockPreparedStatement.getWarnings();
|
||||
ctrlPreparedStatement.setDefaultReturnValue(null);
|
||||
|
||||
ctrlConnection = MockControl.createControl(Connection.class);
|
||||
mockConnection = (Connection) ctrlConnection.getMock();
|
||||
mockConnection.getMetaData();
|
||||
ctrlConnection.setDefaultReturnValue(null);
|
||||
mockConnection.getAutoCommit();
|
||||
ctrlConnection.setDefaultReturnValue(false);
|
||||
mockConnection.prepareStatement("select foo from bar", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
|
||||
ResultSet.HOLD_CURSORS_OVER_COMMIT);
|
||||
ctrlConnection.setReturnValue(mockPreparedStatement);
|
||||
mockConnection.commit();
|
||||
ctrlConnection.setDefaultVoidCallable();
|
||||
mockConnection.close();
|
||||
ctrlConnection.setDefaultVoidCallable();
|
||||
|
||||
ctrlDataSource = MockControl.createControl(DataSource.class);
|
||||
mockDataSource = (DataSource) ctrlDataSource.getMock();
|
||||
mockDataSource.getConnection();
|
||||
ctrlDataSource.setReturnValue(mockConnection);
|
||||
mockDataSource.getConnection();
|
||||
ctrlDataSource.setReturnValue(mockConnection);
|
||||
|
||||
ctrlResultSet.replay();
|
||||
ctrlDataSource.replay();
|
||||
ctrlConnection.replay();
|
||||
ctrlPreparedStatement.replay();
|
||||
|
||||
PlatformTransactionManager tm = new DataSourceTransactionManager(mockDataSource);
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
final JdbcCursorItemReader reader = new JdbcCursorItemReader();
|
||||
reader.setDataSource(mockDataSource);
|
||||
reader.setSql("select foo from bar");
|
||||
final ExecutionContext ec = new ExecutionContext();
|
||||
tt.execute(
|
||||
new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
reader.open(ec);
|
||||
reader.close(ec);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
ctrlDataSource.verify();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user