From dabfda5cb3676caa7d2220aa8c831beb91ddb150 Mon Sep 17 00:00:00 2001 From: trisberg Date: Mon, 15 Dec 2008 15:02:33 +0000 Subject: [PATCH] BATCH-970: backported 2.0 fix - added call to DataSourceUtils to get connection for active transaction --- .../item/database/JdbcCursorItemReader.java | 3 +- .../JdbcCursorItemReaderConfigTests.java | 86 +++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderConfigTests.java diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcCursorItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcCursorItemReader.java index ab07fa93a..ea53d9556 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcCursorItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcCursorItemReader.java @@ -33,6 +33,7 @@ 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; @@ -170,7 +171,7 @@ public class JdbcCursorItemReader extends AbstractBufferedItemReaderItemStream i Assert.state(dataSource != null, "DataSource must not be null."); try { - this.con = dataSource.getConnection(); + this.con = DataSourceUtils.getConnection(dataSource); preparedStatement = this.con.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT); applyStatementSettings(preparedStatement); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderConfigTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderConfigTests.java new file mode 100644 index 000000000..eadec699b --- /dev/null +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderConfigTests.java @@ -0,0 +1,86 @@ +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 { + 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); + + 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(); + } + +}