Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/377.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 Spring:用于动态查询的通用行映射器_Java_Spring_Spring Batch - Fatal编程技术网

Java Spring:用于动态查询的通用行映射器

Java Spring:用于动态查询的通用行映射器,java,spring,spring-batch,Java,Spring,Spring Batch,我正在使用SpringBatch从Oracle读取数据并写入ElasticSearch 我的代码可以很好地用于静态查询。 示例:从employee_表中选择emp_id、emp_name我有一个行映射器类,它将resultSet中的值映射到employee POJO 我的要求是 查询将由用户输入。因此,查询可能如下所示 从employee\u表中选择emp\u id、emp\u name 从customer\u表中选择cust\u id、cust\u name、cust\u age 从地址表中选

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

我的代码可以很好地用于静态查询。 示例:
从employee_表中选择emp_id、emp_name
我有一个行映射器类,它将resultSet中的值映射到employee POJO

我的要求是

查询将由用户输入。因此,查询可能如下所示

  • 从employee\u表中选择emp\u id、emp\u name
  • 从customer\u表中选择cust\u id、cust\u name、cust\u age
  • 从地址表中选择门号、街道名称、位置名称、城市
  • 类似查询
  • 我的问题是

  • 有没有办法根据用户给出的查询动态创建POJO
  • 如果查询像我的情况一样不断变化,行映射器概念会起作用吗
  • 是否有类似于通用行映射器的东西
    谢谢你抽出时间。示例代码将不胜感激

    要回答您的问题:

  • 有没有一种方法可以根据用户的查询动态创建POJO?即使有,我也不知道这会有多大帮助。对于您的用例,我建议只使用
    Map
  • 如果查询不断更改,
    RowMapper
    概念是否有效?如果使用
    Map
    ,则可以使用列名作为键,列值作为值。您应该能够创建一个
    行映射器
    实现来实现这一点
  • 是否有类似于通用的
    行映射器的东西
    -有,但它是专为POJO设计的,因此您需要为此创建自己的行映射器

  • 如果您有需要映射到的对象…

    考虑使用
    RowMapper
    的自定义实现对SQL进行别名,以匹配对象字段名,该实现实际上扩展了
    beanwrapperfiedsetmapper

    因此,如果您的POJO看起来像这样:

    public class Employee {
    
        private String employeeId;
        private String employeeName;
    
        ...
        // getters and setters
    
    }
    
    SELECT emp_id employeeId, emp_name employeeName from employee_table
    
    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]));    
        }
    
    }
    
    然后,您的SQL可以如下所示:

    public class Employee {
    
        private String employeeId;
        private String employeeName;
    
        ...
        // getters and setters
    
    }
    
    SELECT emp_id employeeId, emp_name employeeName from employee_table
    
    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]));    
        }
    
    }
    
    然后,包装好的
    行映射器将如下所示:

    public class Employee {
    
        private String employeeId;
        private String employeeName;
    
        ...
        // getters and setters
    
    }
    
    SELECT emp_id employeeId, emp_name employeeName from employee_table
    
    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]));    
        }
    
    }
    
    然后您的
    ItemSqlParameterSourceProvider
    实现可能如下所示:

    public class MapItemSqlParameterSourceProvider implements
            ItemSqlParameterSourceProvider<Map<String, Object>> {
    
        public SqlParameterSource createSqlParameterSource(Map<String, Object> item) {
            return new MapSqlParameterSource(item);
        }
    
    }
    
    公共类MapItemSqlParameterSourceProvider实现
    ItemSqlParameterSourceProvider{
    公共SqlParameterSource createSqlParameterSource(映射项){
    返回新的MapSqlParameterSource(项);
    }
    }
    
    我使用Spring的ColumnMapRowMapper找到了问题的解决方案。请从xml配置文件中查找代码段。我没有生成任何POJO类。我用一张地图进行管理,并将其插入ES。映射的键名称应与索引中的字段名称匹配

    <step id="slave" xmlns="http://www.springframework.org/schema/batch">
        <tasklet>
            <chunk reader="pagingItemReader" writer="elasticSearcItemWriter"
                processor="itemProcessor" commit-interval="10" />
        </tasklet>
    </step>
    
    
    
    <bean id="pagingItemReader"
            class="org.springframework.batch.item.database.JdbcPagingItemReader"
            scope="step">
            <property name="dataSource" ref="dataSource" />
            <property name="queryProvider">
                <bean
                    class="org.springframework.batch.item.database.support.SqlPagingQueryProviderFactoryBean">
                    <property name="dataSource" ref="dataSource" />
                    <property name="selectClause" value="*******" />
                    <property name="fromClause" value="*******" />
    
                    <property name="whereClause" value="*******" />
                    <property name="sortKey" value="*******" />
                </bean>
    
            </property>
            <!-- Inject via the ExecutionContext in rangePartitioner -->
            <property name="parameterValues">
                <map>
                    <entry key="fromId" value="#{stepExecutionContext[fromId]}" />
                    <entry key="toId" value="#{stepExecutionContext[toId]}" />
                </map>
            </property>
            <property name="pageSize" value="10" />
            <property name="rowMapper">
                <bean class="org.springframework.jdbc.core.ColumnMapRowMapper" />
            </property>
        </bean>
    
    
    
    在我的elasticSearcItemWriter课程中

    public class ElasticSearchItemWriter<T> extends AbstractItemStreamItemWriter<T>
            implements ResourceAwareItemWriterItemStream<T>, InitializingBean {
    ....
    ....
    ....
    @Override
        public void write(List<? extends T> items) throws Exception {
    
    
            client = jestClient.getJestClient();
            if (items.size() > 0) {
                for (Object item : items) {
                    @SuppressWarnings("unchecked")
                    Map<String, Object> map = (Map<String, Object>) item;
                    // Asynch index
                    Index index = new Index.Builder(map).index(Start.prop.getProperty(Constants.ES_INDEX_NAME))
                        .type(Start.prop.getProperty(Constants.ES_INDEX_TYPE)).build();
    
    
                    client.executeAsync(index, new JestResultHandler<JestResult>() {
                        public void failed(Exception ex) {
                        }
    
                        public void completed(JestResult result) {
                        }
                    });
                }
            }
        }
    .....
    ....
    }
    
    公共类ElasticSearchItemWriter扩展了AbstractItemStreamItemWriter
    实现ResourceAwareItemWriterItemStream,初始化Bean{
    ....
    ....
    ....
    @凌驾
    
    public void write(List你可以像下面这样做

    SettingsDto settings = SettingsDao.getById(1, new BeanPropertyRowMapper<>(SettingsDto.class));
    
    我的刀法如下

    SettingsDto getById(int id, final RowMapper<OMoneySettingsDto> mapper);
    

    您可以在这里使用ORM,将查询作为本机查询运行,以获取JPA entitiesHi Michael。感谢您的回答。您能回答第二点吗?我不太明白使用映射将如何解决我的用例。一些代码片段将非常有帮助。感谢您的时间。我相信他指的是
    ColumnMapRowMapper
    。更多信息在我上面的回答中是这样的,但是列名(或别名)将是键,值将是返回映射中的值。这非常有用。谢谢。)@Dean Clark非常喜欢这个实现,并感谢您提供它。我正在尝试查找BeanWrapperFieldSetMapper的导入。您能提供吗?提前感谢!@Nelda.techspires-已添加到上面!