使用SpringBatch JdbcCursorItemReader将列表作为NamedParameters

问题描述 投票:0回答:1

我正在使用以下bean定义来配置读取器,以从Spring Batch项目中的数据库表中读取一些数据。它在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 toRetailSeasonalE3PromotionDTO(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;
}

我将sample code snippet here称为对questions之一的答复-当我们传递一个值时,这似乎是有效的。但是,我的问题是传递一个列表而不是参数中的一个值。这似乎是失败的地方。

java spring spring-batch
1个回答
1
投票

ListPreparedStatementSetter不知道参数类型。如果参数是数组或集合,它将按原样将其设置为第一个占位符,而其他占位符保持不变。因此,错误。在您的示例中,如果为List<Long> keys = Arrays.asList(1, 2),则您的sql语句将为:

SELECT A FROM MYTABLE WHERE KEY IN (?, ?)

如果将singletonMap传递给ListPreparedStatementSetter,它将把keys的值(其类型为List)设置为第一个占位符。第二个占位符将仍然未设置,并且语句的准备将失败。

您可以在将参数传递到ListPreparedStatementSetter之前对其进行展平,它应该可以正常工作。我添加了一个示例,其中介绍了在将参数传递给准备好的语句设置器here之前,如何使参数变平(请参见flatten方法)。

希望这会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.