Java 使用SpringBatch JdbcCursorItemReader,并将列表作为NamedParameters
我使用下面的bean定义来配置一个读卡器,以便在Spring批处理项目中从数据库表中读取一些数据。它正在SQL中使用命名参数。我将java.util.List作为参数传递。但是,当它尝试运行SQL时,我得到了无效的列类型错误 如果我只是硬编码一个值(Java 使用SpringBatch JdbcCursorItemReader,并将列表作为NamedParameters,java,spring,spring-batch,Java,Spring,Spring Batch,我使用下面的bean定义来配置一个读卡器,以便在Spring批处理项目中从数据库表中读取一些数据。它正在SQL中使用命名参数。我将java.util.List作为参数传递。但是,当它尝试运行SQL时,我得到了无效的列类型错误 如果我只是硬编码一个值(namedParameters.put(“keys”,“138219”);),而不是传递一个列表,它就会工作 @Bean public JdbcCursorItemReader<MyDTO> myReader() { JdbcCursor
namedParameters.put(“keys”,“138219”);
),而不是传递一个列表,它就会工作
@Bean
public JdbcCursorItemReader<MyDTO> myReader() {
JdbcCursorItemReader<MyDTO> itemReader = new JdbcCursorItemReader<>();
itemReader.setDataSource(myDatasource);
itemReader.setRowMapper(return new RowMapper<MyDTO>() {
@Override
public MyDTO mapRow(ResultSet resultSet, int rowNum) throws SQLException {
return toMyDto(resultSet);
}
};);
Map<String, Object> namedParameters = new HashMap<>();
List<Long> keys= //Some List
Map<String, List<Long>> singletonMap = Collections.singletonMap("keys", keys);
namedParameters.putAll(singletonMap);
itemReader.setSql(NamedParameterUtils.substituteNamedParameters("SELECT A FROM MYTABLE WHERE KEY IN (:keys)",new MapSqlParameterSource(namedParameters)));
ListPreparedStatementSetter listPreparedStatementSetter = new ListPreparedStatementSetter();
listPreparedStatementSetter.setParameters(
Arrays.asList(NamedParameterUtils.buildValueArray("SELECT A FROM MYTABLE WHERE KEY IN (:keys)", namedParameters)));
itemReader.setPreparedStatementSetter(listPreparedStatementSetter);
return itemReader;
}
@Bean
公共JdbcCursorItemReader myReader(){
JdbcCursorItemReader itemReader=新的JdbcCursorItemReader();
setDataSource(myDatasource);
setRowMapper(返回新的RowMapper(){
@凌驾
公共MyDTO映射行(ResultSet ResultSet,int rowNum)抛出SQLException{
返回toMyDto(resultSet);
}
};);
Map namedParameters=new HashMap();
列表键=//一些列表
Map singletonMap=Collections.singletonMap(“key”,key);
namedParameters.putAll(singletonMap);
itemReader.setSql(NamedParameterUtils.substituteNamedParameters(“从MYTABLE中选择一个关键字(:keys)”,new-MapSqlParameterSource(namedParameters));
ListPreparedStatementSetter ListPreparedStatementSetter=新ListPreparedStatementSetter();
listPreparedStatementSetter.setParameters(
Arrays.asList(NamedParameterUtils.buildValueArray(“从MYTABLE中选择一个输入(:keys)”,namedParameters));
itemReader.setPreparedStatementSetter(listPreparedStatementSetter);
返回项目阅读器;
}
我指的是对其中一个问题的回答——当我们传递一个值时,它似乎起了作用。但是,我的问题是在参数中传递一个列表而不是一个值。这就是它似乎失败的地方。ListPreparedStatementSetter不知道参数类型。如果某个参数是数组或集合,它将按原样将其设置为第一个占位符,而不设置其他占位符。因此出现了错误。在您的示例中,如果
List keys=Arrays.asList(1,2)
,您的sql语句将是:
SELECT A FROM MYTABLE WHERE KEY IN (?, ?)
如果将singletonMap
传递给ListPreparedStatementSetter
,它会将键的值设置为第一个占位符(类型为List
)。第二个占位符仍将未设置,语句的准备将失败
您可以在将参数传递到ListPreparedStatementSetter
之前将其展平,它应该可以正常工作。我添加了一个示例,介绍了如何在将参数传递给准备好的语句设置器之前展平参数(请参见flatte
method)
希望这有帮助