Skip to content

Commit 281b387

Browse files
committed
Added AbstractCursorItemReader.connectionAutoCommit to allow override of cursor connection autoCommit value
autoCommit value is restored after connection use.
1 parent 26b02fb commit 281b387

File tree

2 files changed

+71
-2
lines changed

2 files changed

+71
-2
lines changed

spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/AbstractCursorItemReader.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2006-2013 the original author or authors.
2+
* Copyright 2006-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -134,6 +134,9 @@ public abstract class AbstractCursorItemReader<T> extends AbstractItemCountingIt
134134

135135
private boolean useSharedExtendedConnection = false;
136136

137+
private Boolean connectionAutoCommit;
138+
139+
private Boolean initialConnectionAutoCommit;
137140

138141
public AbstractCursorItemReader() {
139142
super();
@@ -356,6 +359,25 @@ public boolean isUseSharedExtendedConnection() {
356359
return useSharedExtendedConnection;
357360
}
358361

362+
/**
363+
* Set whether "autoCommit" should be overridden for the connection used by the cursor. If not set, defaults to
364+
* Connection / Datasource default configuration.
365+
*
366+
* @param autoCommit value used for {@link Connection#setAutoCommit(boolean)}.
367+
*/
368+
public void setConnectionAutoCommit(boolean autoCommit) {
369+
this.connectionAutoCommit = autoCommit;
370+
}
371+
372+
/**
373+
* Return whether "autoCommit" should be overridden for the connection used by the cursor.
374+
*
375+
* @return the "autoCommit" value, or {@code null} if none to be applied.
376+
*/
377+
public Boolean getConnectionAutoCommit() {
378+
return this.connectionAutoCommit;
379+
}
380+
359381
public abstract String getSql();
360382

361383
/**
@@ -380,6 +402,9 @@ protected void doClose() throws Exception {
380402
JdbcUtils.closeResultSet(this.rs);
381403
rs = null;
382404
cleanupOnClose();
405+
if (this.initialConnectionAutoCommit != null) {
406+
this.con.setAutoCommit(initialConnectionAutoCommit);
407+
}
383408
if (useSharedExtendedConnection && dataSource instanceof ExtendedConnectionDataSourceProxy) {
384409
((ExtendedConnectionDataSourceProxy)dataSource).stopCloseSuppression(this.con);
385410
if (!TransactionSynchronizationManager.isActualTransactionActive()) {
@@ -424,6 +449,10 @@ protected void initializeConnection() {
424449
else {
425450
this.con = dataSource.getConnection();
426451
}
452+
if (this.connectionAutoCommit != null && this.con.getAutoCommit() != this.connectionAutoCommit) {
453+
this.initialConnectionAutoCommit = this.con.getAutoCommit();
454+
this.con.setAutoCommit(this.connectionAutoCommit);
455+
}
427456
}
428457
catch (SQLException se) {
429458
close();

spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderConfigTests.java

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515
*/
1616
package org.springframework.batch.item.database;
1717

18+
import static org.junit.Assert.assertEquals;
1819
import static org.mockito.Mockito.mock;
20+
import static org.mockito.Mockito.reset;
21+
import static org.mockito.Mockito.times;
22+
import static org.mockito.Mockito.verify;
1923
import static org.mockito.Mockito.when;
2024

2125
import java.sql.Connection;
@@ -25,8 +29,9 @@
2529
import javax.sql.DataSource;
2630

2731
import org.junit.Test;
28-
import org.junit.runners.JUnit4;
2932
import org.junit.runner.RunWith;
33+
import org.junit.runners.JUnit4;
34+
import org.mockito.ArgumentCaptor;
3035
import org.springframework.batch.item.ExecutionContext;
3136
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
3237
import org.springframework.transaction.PlatformTransactionManager;
@@ -100,4 +105,39 @@ public Void doInTransaction(TransactionStatus status) {
100105
});
101106
}
102107

108+
@Test
109+
public void testOverrideConnectionAutoCommit() throws Exception {
110+
boolean initialAutoCommit= false;
111+
boolean neededAutoCommit = true;
112+
113+
DataSource ds = mock(DataSource.class);
114+
Connection con = mock(Connection.class);
115+
when(con.getAutoCommit()).thenReturn(initialAutoCommit);
116+
PreparedStatement ps = mock(PreparedStatement.class);
117+
when(con.prepareStatement("select foo from bar", ResultSet.TYPE_FORWARD_ONLY,
118+
ResultSet.CONCUR_READ_ONLY)).thenReturn(ps);
119+
when(ds.getConnection()).thenReturn(con);
120+
121+
final JdbcCursorItemReader<String> reader = new JdbcCursorItemReader<String>();
122+
reader.setDataSource(ds);
123+
reader.setSql("select foo from bar");
124+
reader.setConnectionAutoCommit(neededAutoCommit);
125+
126+
// Check "open" outside of a transaction (see AbstractStep#execute())
127+
final ExecutionContext ec = new ExecutionContext();
128+
reader.open(ec);
129+
130+
ArgumentCaptor<Boolean> autoCommitCaptor = ArgumentCaptor.forClass(Boolean.class);
131+
verify(con, times(1)).setAutoCommit(autoCommitCaptor.capture());
132+
assertEquals(neededAutoCommit, autoCommitCaptor.getValue());
133+
134+
reset(con);
135+
reader.close();
136+
137+
// Check restored autocommit value
138+
autoCommitCaptor = ArgumentCaptor.forClass(Boolean.class);
139+
verify(con, times(1)).setAutoCommit(autoCommitCaptor.capture());
140+
assertEquals(initialAutoCommit, autoCommitCaptor.getValue());
141+
}
142+
103143
}

0 commit comments

Comments
 (0)