IN PROGRESS - BATCH-712: Upgrade ItemReaders to use Parameterized types
This commit is contained in:
@@ -26,7 +26,7 @@ import com.ibatis.sqlmap.client.SqlMapClient;
|
||||
* @author Lucas Ward
|
||||
* @see DrivingQueryItemReader
|
||||
*/
|
||||
public class IbatisKeyCollector extends ExecutionContextUserSupport implements KeyCollector {
|
||||
public class IbatisKeyCollector<T> extends ExecutionContextUserSupport implements KeyCollector<T> {
|
||||
|
||||
private static final String RESTART_KEY = "key.index";
|
||||
|
||||
@@ -46,7 +46,7 @@ public class IbatisKeyCollector extends ExecutionContextUserSupport implements K
|
||||
* @see KeyCollector#retrieveKeys()
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Object> retrieveKeys(ExecutionContext executionContext) {
|
||||
public List<T> retrieveKeys(ExecutionContext executionContext) {
|
||||
if (executionContext.containsKey(getKey(RESTART_KEY))) {
|
||||
Object key = executionContext.get(getKey(RESTART_KEY));
|
||||
return sqlMapClientTemplate.queryForList(restartQueryId, key);
|
||||
|
||||
@@ -49,7 +49,7 @@ import org.springframework.util.StringUtils;
|
||||
* @see DrivingQueryItemReader
|
||||
* @see ItemPreparedStatementSetter
|
||||
*/
|
||||
public class MultipleColumnJdbcKeyCollector extends ExecutionContextUserSupport implements KeyCollector {
|
||||
public class MultipleColumnJdbcKeyCollector<T> extends ExecutionContextUserSupport implements KeyCollector<T> {
|
||||
|
||||
private static final String CURRENT_KEY = "current.key";
|
||||
|
||||
@@ -89,7 +89,7 @@ public class MultipleColumnJdbcKeyCollector extends ExecutionContextUserSupport
|
||||
* #retrieveKeys()
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Object> retrieveKeys(ExecutionContext executionContext) {
|
||||
public List<T> retrieveKeys(ExecutionContext executionContext) {
|
||||
|
||||
Assert.state(keyMapper != null, "KeyMapper must not be null.");
|
||||
Assert.state(StringUtils.hasText(restartSql), "The RestartQuery must not be null or empty"
|
||||
|
||||
@@ -29,25 +29,30 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Jdbc {@link KeyCollector} implementation that only works for a single column key. A sql query must be passed in which
|
||||
* will be used to return a list of keys. Each key will be mapped by a {@link RowMapper} that returns a mapped key. By
|
||||
* default, the {@link SingleColumnRowMapper} is used, and will convert keys into well known types at runtime. It is
|
||||
* extremely important to note that only one column should be mapped to an object and returned as a key. If multiple
|
||||
* columns are returned as a key in this strategy, then restart will not function properly. Instead a strategy that
|
||||
* supports keys comprised of multiple columns should be used.
|
||||
* Jdbc {@link KeyCollector} implementation that only works for a single column
|
||||
* key. A sql query must be passed in which will be used to return a list of
|
||||
* keys. Each key will be mapped by a {@link RowMapper} that returns a mapped
|
||||
* key. By default, the {@link SingleColumnRowMapper} is used, and will convert
|
||||
* keys into well known types at runtime. It is extremely important to note that
|
||||
* only one column should be mapped to an object and returned as a key. If
|
||||
* multiple columns are returned as a key in this strategy, then restart will
|
||||
* not function properly. Instead a strategy that supports keys comprised of
|
||||
* multiple columns should be used.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Restartability: Because the key is only one column, restart is made much more simple. Before each commit, the last
|
||||
* processed key is returned to be stored as restart data. Upon restart, that same key is given back to restore from,
|
||||
* using a separate 'RestartQuery'. This means that only the keys remaining to be processed are returned, rather than
|
||||
* returning the original list of keys and iterating forward to that last committed point.
|
||||
* Restartability: Because the key is only one column, restart is made much more
|
||||
* simple. Before each commit, the last processed key is returned to be stored
|
||||
* as restart data. Upon restart, that same key is given back to restore from,
|
||||
* using a separate 'RestartQuery'. This means that only the keys remaining to
|
||||
* be processed are returned, rather than returning the original list of keys
|
||||
* and iterating forward to that last committed point.
|
||||
* </p>
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @see SingleColumnRowMapper
|
||||
*/
|
||||
public class SingleColumnJdbcKeyCollector extends ExecutionContextUserSupport implements KeyCollector {
|
||||
public class SingleColumnJdbcKeyCollector<T> extends ExecutionContextUserSupport implements KeyCollector<T> {
|
||||
|
||||
private static final String RESTART_KEY = "key";
|
||||
|
||||
@@ -64,8 +69,8 @@ public class SingleColumnJdbcKeyCollector extends ExecutionContextUserSupport im
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance using the provided jdbcTemplate and string representing the sql statement that should
|
||||
* be used to retrieve keys.
|
||||
* Constructs a new instance using the provided jdbcTemplate and string
|
||||
* representing the sql statement that should be used to retrieve keys.
|
||||
*
|
||||
* @param jdbcTemplate
|
||||
* @param sql
|
||||
@@ -83,18 +88,21 @@ public class SingleColumnJdbcKeyCollector extends ExecutionContextUserSupport im
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.io.driving.KeyGenerationStrategy#retrieveKeys()
|
||||
* @see
|
||||
* org.springframework.batch.io.driving.KeyGenerationStrategy#retrieveKeys()
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Object> retrieveKeys(ExecutionContext executionContext) {
|
||||
public List<T> retrieveKeys(ExecutionContext executionContext) {
|
||||
|
||||
Assert.notNull(executionContext, "The ExecutionContext must not be null");
|
||||
|
||||
if (executionContext.containsKey(getKey(RESTART_KEY))) {
|
||||
Assert.state(StringUtils.hasText(restartSql), "The restart sql query must not be null or empty"
|
||||
+ " in order to restart.");
|
||||
return jdbcTemplate.query(restartSql, new Object[] { executionContext.get(getKey(RESTART_KEY)) }, keyMapper);
|
||||
} else {
|
||||
+ " in order to restart.");
|
||||
return jdbcTemplate
|
||||
.query(restartSql, new Object[] { executionContext.get(getKey(RESTART_KEY)) }, keyMapper);
|
||||
}
|
||||
else {
|
||||
return jdbcTemplate.query(sql, keyMapper);
|
||||
}
|
||||
}
|
||||
@@ -113,7 +121,8 @@ public class SingleColumnJdbcKeyCollector extends ExecutionContextUserSupport im
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
* @see
|
||||
* org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(jdbcTemplate, "JdbcTemplate must not be null.");
|
||||
@@ -130,7 +139,8 @@ public class SingleColumnJdbcKeyCollector extends ExecutionContextUserSupport im
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the SQL query to be used to return the remaining keys to be processed.
|
||||
* Set the SQL query to be used to return the remaining keys to be
|
||||
* processed.
|
||||
*
|
||||
* @param restartSql
|
||||
*/
|
||||
@@ -146,7 +156,7 @@ public class SingleColumnJdbcKeyCollector extends ExecutionContextUserSupport im
|
||||
public void setSql(String sql) {
|
||||
this.sql = sql;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the {@link JdbcTemplate} to be used.
|
||||
*
|
||||
|
||||
@@ -18,13 +18,13 @@ import org.springframework.util.Assert;
|
||||
public abstract class AbstractDataSourceItemReaderIntegrationTests extends
|
||||
AbstractTransactionalDataSourceSpringContextTests {
|
||||
|
||||
protected ItemReader reader;
|
||||
protected ItemReader<Foo> reader;
|
||||
protected ExecutionContext executionContext;
|
||||
|
||||
/**
|
||||
* @return configured input source ready for use
|
||||
*/
|
||||
protected abstract ItemReader createItemReader() throws Exception;
|
||||
protected abstract ItemReader<Foo> createItemReader() throws Exception;
|
||||
|
||||
protected String[] getConfigLocations() {
|
||||
return new String[] { "org/springframework/batch/item/database/data-source-context.xml" };
|
||||
@@ -245,11 +245,11 @@ public abstract class AbstractDataSourceItemReaderIntegrationTests extends
|
||||
reader.reset();
|
||||
}
|
||||
|
||||
private ItemStream getAsItemStream(ItemReader source) {
|
||||
private ItemStream getAsItemStream(ItemReader<Foo> source) {
|
||||
return (ItemStream) source;
|
||||
}
|
||||
|
||||
private InitializingBean getAsInitializingBean(ItemReader source) {
|
||||
private InitializingBean getAsInitializingBean(ItemReader<Foo> source) {
|
||||
return (InitializingBean) source;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,14 +17,14 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public abstract class AbstractJdbcItemReaderIntegrationTests extends AbstractTransactionalDataSourceSpringContextTests {
|
||||
|
||||
protected ItemReader itemReader;
|
||||
protected ItemReader<Foo> itemReader;
|
||||
|
||||
protected ExecutionContext executionContext;
|
||||
|
||||
/**
|
||||
* @return input source with all necessary dependencies set
|
||||
*/
|
||||
protected abstract ItemReader createItemReader() throws Exception;
|
||||
protected abstract ItemReader<Foo> createItemReader() throws Exception;
|
||||
|
||||
protected String[] getConfigLocations(){
|
||||
return new String[] { "org/springframework/batch/item/database/data-source-context.xml"};
|
||||
@@ -160,15 +160,15 @@ public abstract class AbstractJdbcItemReaderIntegrationTests extends AbstractTra
|
||||
itemReader.reset();
|
||||
}
|
||||
|
||||
private ItemStream getAsItemStream(ItemReader source) {
|
||||
private ItemStream getAsItemStream(ItemReader<Foo> source) {
|
||||
return (ItemStream) source;
|
||||
}
|
||||
|
||||
private InitializingBean getAsInitializingBean(ItemReader source) {
|
||||
private InitializingBean getAsInitializingBean(ItemReader<Foo> source) {
|
||||
return (InitializingBean) source;
|
||||
}
|
||||
|
||||
private DisposableBean getAsDisposableBean(ItemReader source) {
|
||||
private DisposableBean getAsDisposableBean(ItemReader<Foo> source) {
|
||||
return (DisposableBean) source;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.springframework.util.Assert;
|
||||
|
||||
public class DrivingQueryItemReaderTests extends TestCase {
|
||||
|
||||
DrivingQueryItemReader itemReader;
|
||||
DrivingQueryItemReader<Foo> itemReader;
|
||||
|
||||
static {
|
||||
TransactionSynchronizationManager.initSynchronization();
|
||||
@@ -27,9 +27,9 @@ public class DrivingQueryItemReaderTests extends TestCase {
|
||||
itemReader = createItemReader();
|
||||
}
|
||||
|
||||
private DrivingQueryItemReader createItemReader() throws Exception {
|
||||
private DrivingQueryItemReader<Foo> createItemReader() throws Exception {
|
||||
|
||||
DrivingQueryItemReader inputSource = new DrivingQueryItemReader();
|
||||
DrivingQueryItemReader<Foo> inputSource = new DrivingQueryItemReader<Foo>();
|
||||
inputSource.setKeyCollector(new MockKeyGenerator());
|
||||
inputSource.setSaveState(true);
|
||||
|
||||
@@ -159,10 +159,10 @@ public class DrivingQueryItemReaderTests extends TestCase {
|
||||
|
||||
public void testRetriveZeroKeys() {
|
||||
|
||||
itemReader.setKeyCollector(new KeyCollector() {
|
||||
itemReader.setKeyCollector(new KeyCollector<Foo>() {
|
||||
|
||||
public List<Object> retrieveKeys(ExecutionContext executionContext) {
|
||||
return new ArrayList<Object>();
|
||||
public List<Foo> retrieveKeys(ExecutionContext executionContext) {
|
||||
return new ArrayList<Foo>();
|
||||
}
|
||||
|
||||
public void updateContext(Object key,
|
||||
@@ -184,19 +184,19 @@ public class DrivingQueryItemReaderTests extends TestCase {
|
||||
itemReader.reset();
|
||||
}
|
||||
|
||||
private InitializingBean getAsInitializingBean(ItemReader source) {
|
||||
private InitializingBean getAsInitializingBean(ItemReader<Foo> source) {
|
||||
return (InitializingBean) source;
|
||||
}
|
||||
|
||||
private ItemStream getAsItemStream(ItemReader source) {
|
||||
private ItemStream getAsItemStream(ItemReader<Foo> source) {
|
||||
return (ItemStream) source;
|
||||
}
|
||||
|
||||
private static class MockKeyGenerator implements KeyCollector {
|
||||
private static class MockKeyGenerator implements KeyCollector<Foo> {
|
||||
|
||||
static ExecutionContext streamContext;
|
||||
List<Object> keys;
|
||||
List<Object> restartKeys;
|
||||
List<Foo> keys;
|
||||
List<Foo> restartKeys;
|
||||
static final String RESTART_KEY = "restart.keys";
|
||||
|
||||
static {
|
||||
@@ -207,14 +207,14 @@ public class DrivingQueryItemReaderTests extends TestCase {
|
||||
|
||||
public MockKeyGenerator() {
|
||||
|
||||
keys = new ArrayList<Object>();
|
||||
keys = new ArrayList<Foo>();
|
||||
keys.add(new Foo(1, "1", 1));
|
||||
keys.add(new Foo(2, "2", 2));
|
||||
keys.add(new Foo(3, "3", 3));
|
||||
keys.add(new Foo(4, "4", 4));
|
||||
keys.add(new Foo(5, "5", 5));
|
||||
|
||||
restartKeys = new ArrayList<Object>();
|
||||
restartKeys = new ArrayList<Foo>();
|
||||
restartKeys.add(new Foo(3, "3", 3));
|
||||
restartKeys.add(new Foo(4, "4", 4));
|
||||
restartKeys.add(new Foo(5, "5", 5));
|
||||
@@ -224,7 +224,7 @@ public class DrivingQueryItemReaderTests extends TestCase {
|
||||
return streamContext;
|
||||
}
|
||||
|
||||
public List<Object> retrieveKeys(ExecutionContext executionContext) {
|
||||
public List<Foo> retrieveKeys(ExecutionContext executionContext) {
|
||||
if (executionContext.containsKey(RESTART_KEY)) {
|
||||
return restartKeys;
|
||||
} else {
|
||||
|
||||
@@ -3,26 +3,27 @@ package org.springframework.batch.item.database;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemStream;
|
||||
import org.springframework.batch.item.sample.Foo;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
class FooItemReader implements ItemStream, ItemReader, DisposableBean, InitializingBean {
|
||||
class FooItemReader implements ItemStream, ItemReader<Foo>, DisposableBean, InitializingBean {
|
||||
|
||||
DrivingQueryItemReader itemReader;
|
||||
DrivingQueryItemReader<Foo> itemReader;
|
||||
|
||||
public void setItemReader(DrivingQueryItemReader itemReader) {
|
||||
public void setItemReader(DrivingQueryItemReader<Foo> itemReader) {
|
||||
this.itemReader = itemReader;
|
||||
}
|
||||
|
||||
FooDao fooDao = new SingleKeyFooDao();
|
||||
|
||||
public FooItemReader(DrivingQueryItemReader inputSource, JdbcTemplate jdbcTemplate) {
|
||||
public FooItemReader(DrivingQueryItemReader<Foo> inputSource, JdbcTemplate jdbcTemplate) {
|
||||
this.itemReader = inputSource;
|
||||
fooDao.setJdbcTemplate(jdbcTemplate);
|
||||
}
|
||||
|
||||
public Object read() {
|
||||
public Foo read() {
|
||||
Object key = itemReader.read();
|
||||
if (key != null) {
|
||||
return fooDao.getFoo(key);
|
||||
|
||||
@@ -3,13 +3,14 @@ package org.springframework.batch.item.database;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.sample.Foo;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
|
||||
|
||||
public class HibernateCursorItemReaderCommonTests extends CommonDatabaseItemStreamItemReaderTests {
|
||||
|
||||
protected ItemReader getItemReader() throws Exception {
|
||||
protected ItemReader<Foo> getItemReader() throws Exception {
|
||||
|
||||
SessionFactory sessionFactory = createSessionFactory();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user