考えられる解決策の 1 つは、Continuable
Tasklet を確認することです。タスクレットは、Spring Batch によって管理されるように「ループ」できますResultSet.next()
。これにより、フレームワークがストリームを閉じることなく、1 回のアクセスでレコードを取得して処理することができます。
package de.incompleteco.spring.batch.step.tasklet;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
public class ScrollableResultsetTasklet implements Tasklet {
private boolean open = false;
@Resource
private DataSource dataSource;
private String sql = "select * from test_table";
private ResultSet rs;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
if (!open) {
//open the resultset
rs = open();
open = true;//set to open
}//end if
//move
rs.next();
if (!rs.isAfterLast()) {
//show
System.out.println(rs.getInt(1));
return RepeatStatus.CONTINUABLE;
}//end if
//done
return RepeatStatus.FINISHED;
}
protected ResultSet open() throws SQLException {
return dataSource.getConnection().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY).executeQuery(sql);
}
}
もちろん、これは「再起動可能」ではありませんが、スクロール可能な結果セットでもありません(追加の作業は必要ありません)。
チャンクから読み取る場合は、バッチ チャンク間で独自の「状態」を維持する別の pogo に結果セット マネージャーを「外部化」することを検討できます。これは次のようになります。
package de.incompleteco.spring.batch.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.sql.DataSource;
public class ScrollableResultSetService {
private boolean open = false;
@Resource
private DataSource dataSource;
private String sql = "select * from test_table";
private ResultSet rs;
/**
* retrieve the result set in a 'next' state
* @return
* @throws SQLException
*/
public ResultSet getNext() throws SQLException {
if (rs == null || !open) {
//open the resulset
rs = dataSource.getConnection().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY).executeQuery(sql);
}//end if
//move
rs.next();
//test
if (rs.isAfterLast()) {
return null;
}//end if
return rs;
}
}
itemreader は次のようになります。
package de.incompleteco.spring.batch.step.item;
import java.sql.ResultSet;
import javax.annotation.Resource;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import de.incompleteco.spring.batch.service.ScrollableResultSetService;
public class ScrollableResultSetItemReader implements ItemReader<T> {
@Resource
private ScrollableResultSetService service;
@Override
public T read() throws Exception, UnexpectedInputException, ParseException,NonTransientResourceException {
ResultSet rs = service.getNext();
if (rs == null) {
return null;//don't continue
}//end if
//process the result set into your object
//...
//return object
return T;
}
}