Spring:用于动态查询的通用RowMapper

And*_*ndy 2 java spring spring-batch

我正在使用SpringBatch从Oracle读取并写入ElasticSearch.

我的代码适用于静态查询.示例: select emp_id, emp_name from employee_table我有一个RowMapper类,它将resultSet中的值映射到Employee POJO.

我的要求是

查询将由用户输入.所以查询可能如下

  1. select emp_id, emp_name from employee_table
  2. select cust_id, cust_name, cust_age from customer_table
  3. select door_no, street_name, loc_name, city from address_table
  4. Similar queries

我的问题是

  1. 我有没有办法根据用户提供的查询动态创建POJO?
  2. 如果查询在我的情况下不断变化,RowMapper概念会起作用吗?
  3. 是否有类似通用rowmapper的东西?

谢谢你的时间.示例代码将非常感激.

Dea*_*ark 7

如果你有对象,你需要映射到...

考虑使用RowMapper实际扩展的自定义实现对SQL进行别名以匹配对象字段名称BeanWrapperFieldSetMapper

所以如果你的POJO看起来像这样:

public class Employee {

    private String employeeId;
    private String employeeName;

    ...
    // getters and setters

}
Run Code Online (Sandbox Code Playgroud)

然后你的SQL看起来像这样:

SELECT emp_id employeeId, emp_name employeeName from employee_table
Run Code Online (Sandbox Code Playgroud)

然后你的包装RowMapper看起来像这样:

import org.springframework.jdbc.core.RowMapper
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper

public class BeanWrapperRowMapper<T> extends BeanWrapperFieldSetMapper<T> implements RowMapper<T> {

    @Override
    public T mapRow(final ResultSet rs, final int rowNum) throws SQLException {
        final FieldSet fs = getFieldSet(rs);
        try {
            return super.mapFieldSet(fs);
        } catch (final BindException e) {
            throw new IllegalArgumentException("Could not bind bean to FieldSet", e);
        }
    }

    private FieldSet getFieldSet(final ResultSet rs) throws SQLException {
        final ResultSetMetaData metaData = rs.getMetaData();
        final int columnCount = metaData.getColumnCount();

        final List<String> tokens = new ArrayList<>();
        final List<String> names = new ArrayList<>();

        for (int i = 1; i <= columnCount; i++) {
            tokens.add(rs.getString(i));
            names.add(metaData.getColumnName(i));
        }

        return new DefaultFieldSet(tokens.toArray(new String[0]), names.toArray(new String[0]));    
    }

}
Run Code Online (Sandbox Code Playgroud)

另外...

如果您没有要映射到的任何POJO,请使用开箱ColumnMapRowMapper即可获取Map<String,Object>列名称的map()(让我们称之为COL_A,COL_B,COL_C)为值.然后,如果您的编写器类似于JdbcBatchItemWriter您可以将命名参数设置为:

INSERT TO ${schema}.TARGET_TABLE (COL_1, COL_2, COL_3) values (:COL_A, :COL_B, :COL_C)
Run Code Online (Sandbox Code Playgroud)

然后你的ItemSqlParameterSourceProvider实现看起来像这样:

public class MapItemSqlParameterSourceProvider implements
        ItemSqlParameterSourceProvider<Map<String, Object>> {

    public SqlParameterSource createSqlParameterSource(Map<String, Object> item) {
        return new MapSqlParameterSource(item);
    }

}
Run Code Online (Sandbox Code Playgroud)