Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/397.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用SpringBatch JdbcCursorItemReader,并将列表作为NamedParameters_Java_Spring_Spring Batch - Fatal编程技术网

Java 使用SpringBatch JdbcCursorItemReader,并将列表作为NamedParameters

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

我使用下面的bean定义来配置一个读卡器,以便在Spring批处理项目中从数据库表中读取一些数据。它正在SQL中使用命名参数。我将java.util.List作为参数传递。但是,当它尝试运行SQL时,我得到了无效的列类型错误

如果我只是硬编码一个值(
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)

希望这有帮助