Java 结果集元数据作为Spring批处理中CSV文件的头

Java 结果集元数据作为Spring批处理中CSV文件的头,java,spring-batch,Java,Spring Batch,我正在编写一个代码,从SQL存储过程的结果集生成CSV文件。通过使用Spring批处理框架本身,我几乎使所有内容都通用,但头除外。我希望resultset的元数据作为头。我不想扩展StoredProcedureItemReader并执行它。在Spring批处理框架中是否有任何类/项可以像我上面问的那样编写头,或者在StoredProcedureItemReader或FlatFileItemWriter中是否有任何属性可以执行此操作。我希望它是通用的,因为我希望对多个存储过程使用相同的代码。spr

我正在编写一个代码,从SQL存储过程的结果集生成CSV文件。通过使用Spring批处理框架本身,我几乎使所有内容都通用,但头除外。我希望resultset的元数据作为头。我不想扩展
StoredProcedureItemReader
并执行它。在Spring批处理框架中是否有任何类/项可以像我上面问的那样编写头,或者在
StoredProcedureItemReader
FlatFileItemWriter
中是否有任何属性可以执行此操作。我希望它是通用的,因为我希望对多个存储过程使用相同的代码。

spring Batch提供了创建文件头的
FlatFileHeaderCallback
。 您需要实现
writeHeader(Writer-Writer)
方法

在WriteHeader方法中,您需要编写如下内容

1在该类中注入
JdbcTemplate

然后

List List=jdbcTemplate.query(“从1=2的表中选择*,新建YourMapper())
在映射器中-从
ResultSet
对象可以获得
ResultSetMetaData
*。 现在使用
ResultSetMetaData
可以获得所有列名的列表。
然后从mapper返回此列表,spring Batch提供了用于创建文件头的FlatFileHeaderCallback。 您需要实现
writeHeader(Writer-Writer)
方法

在WriteHeader方法中,您需要编写如下内容

1在该类中注入
JdbcTemplate

然后

List List=jdbcTemplate.query(“从1=2的表中选择*,新建YourMapper())
在映射器中-从
ResultSet
对象可以获得
ResultSetMetaData
*。 现在使用
ResultSetMetaData
可以获得所有列名的列表。
然后从映射器返回此列表

实现
FlatFileHeaderCallback
如下

public class TestClass implements FlatFileHeaderCallback  {

    @Autowired
    private JdbcTemplate jdbcTemplate; //IF you have jdbcTemplate bean or use data source run the SQL


    @Override
    public void writeHeader(Writer writer) throws IOException {


        List<String> list = jdbcTemplate.query("Select * From table where 1=2",new YourMapper()) ;
        list.toString();
        writer.write(list.toString());      
    }

}
public class YourDBMapper implements ResultSetExtractor<List<String>> {

    List<String> list = new List<>();
    @Override
    public List<String> extractData(ResultSet rs){      

        ResultSetMetaData meta = rs.getMetaData();    

        for (int i = 1; i <=  meta.getColumnCount(); i++) 
            list.add(meta.getColumnName(i));        

        return list;
    }

}
公共类TestClass实现FlatFileHeaderCallback{
@自动连线
私有JdbcTemplate JdbcTemplate;//如果您有JdbcTemplate bean或使用数据源,请运行SQL
@凌驾
public void writeHeader(Writer-Writer)引发IOException{
List List=jdbcTemplate.query(“从表中选择*,其中1=2”,新建YourMapper());
list.toString();
writer.write(list.toString());
}
}
映射器将是这样的

public class TestClass implements FlatFileHeaderCallback  {

    @Autowired
    private JdbcTemplate jdbcTemplate; //IF you have jdbcTemplate bean or use data source run the SQL


    @Override
    public void writeHeader(Writer writer) throws IOException {


        List<String> list = jdbcTemplate.query("Select * From table where 1=2",new YourMapper()) ;
        list.toString();
        writer.write(list.toString());      
    }

}
public class YourDBMapper implements ResultSetExtractor<List<String>> {

    List<String> list = new List<>();
    @Override
    public List<String> extractData(ResultSet rs){      

        ResultSetMetaData meta = rs.getMetaData();    

        for (int i = 1; i <=  meta.getColumnCount(); i++) 
            list.add(meta.getColumnName(i));        

        return list;
    }

}
public类YourDBMapper实现ResultSetExtractor{
列表=新列表();
@凌驾
公共列表提取数据(结果集rs){
ResultSetMetaData meta=rs.getMetaData();

对于(int i=1;i实现
FlatFileHeaderCallback
,如下所示

public class TestClass implements FlatFileHeaderCallback  {

    @Autowired
    private JdbcTemplate jdbcTemplate; //IF you have jdbcTemplate bean or use data source run the SQL


    @Override
    public void writeHeader(Writer writer) throws IOException {


        List<String> list = jdbcTemplate.query("Select * From table where 1=2",new YourMapper()) ;
        list.toString();
        writer.write(list.toString());      
    }

}
public class YourDBMapper implements ResultSetExtractor<List<String>> {

    List<String> list = new List<>();
    @Override
    public List<String> extractData(ResultSet rs){      

        ResultSetMetaData meta = rs.getMetaData();    

        for (int i = 1; i <=  meta.getColumnCount(); i++) 
            list.add(meta.getColumnName(i));        

        return list;
    }

}
公共类TestClass实现FlatFileHeaderCallback{
@自动连线
私有JdbcTemplate JdbcTemplate;//如果您有JdbcTemplate bean或使用数据源,请运行SQL
@凌驾
public void writeHeader(Writer-Writer)引发IOException{
List List=jdbcTemplate.query(“从表中选择*,其中1=2”,新建YourMapper());
list.toString();
writer.write(list.toString());
}
}
映射器将是这样的

public class TestClass implements FlatFileHeaderCallback  {

    @Autowired
    private JdbcTemplate jdbcTemplate; //IF you have jdbcTemplate bean or use data source run the SQL


    @Override
    public void writeHeader(Writer writer) throws IOException {


        List<String> list = jdbcTemplate.query("Select * From table where 1=2",new YourMapper()) ;
        list.toString();
        writer.write(list.toString());      
    }

}
public class YourDBMapper implements ResultSetExtractor<List<String>> {

    List<String> list = new List<>();
    @Override
    public List<String> extractData(ResultSet rs){      

        ResultSetMetaData meta = rs.getMetaData();    

        for (int i = 1; i <=  meta.getColumnCount(); i++) 
            list.add(meta.getColumnName(i));        

        return list;
    }

}
public类YourDBMapper实现ResultSetExtractor{
列表=新列表();
@凌驾
公共列表提取数据(结果集rs){
ResultSetMetaData meta=rs.getMetaData();

对于(inti=1;i实际上,我的代码中有如下内容来获取元数据

    @Scope("step")
    public class CustomColumnMapRowMapper extends ColumnMapRowMapper{
    private static boolean isMetadataSet = false;
    @Autowired
    private StepExecution stepExecution;
    @Autowired
    private String delimiter;

    private String metadata="";
    @Override
    public Map<String, Object> mapRow(ResultSet rs, int rowNum) throws SQLException {
        System.out.println("Inside custom row mapper "+this.getClass().getName());
        ResultSetMetaData rsmd = rs.getMetaData();

        int columnCount = rsmd.getColumnCount();
        Map<String, Object> mapOfColValues = createColumnMap(columnCount);
        for (int i = 1; i <= columnCount; i++) {
            String key = getColumnKey(JdbcUtils.lookupColumnName(rsmd, i));
            if(!this.isMetadataSet){
                if(i==columnCount){
                    metadata=metadata.concat(key);
                    break;
                }
                metadata=metadata.concat(key).concat(delimiter);
            }
            Object obj = getColumnValue(rs, i);
            mapOfColValues.put(key, obj);
        }
        if(!this.isMetadataSet){
            this.stepExecution.getJobExecution().getExecutionContext().put("metadata", this.metadata);
            this.isMetadataSet = true;
            System.out.println("Metadata retrieved is "+this.stepExecution.getJobExecution().getExecutionContext().get("metadata"));
        }

        //System.out.println("Metadata is "+this.metadata);
        return mapOfColValues;
    }
请查看我的作业配置

<batch:job id="ReportJob">
    <batch:step id="step1">
        <batch:tasklet transaction-manager="transactionManager">
            <batch:chunk reader="databaseItemReader" writer="flatFileItemWriter"
                processor="itemProcessor" commit-interval="100" />
        </batch:tasklet>
    </batch:step>
    <batch:listeners>
        <batch:listener ref="jobListener" />
    </batch:listeners>
</batch:job>

实际上,我的代码中有如下内容来获取元数据

    @Scope("step")
    public class CustomColumnMapRowMapper extends ColumnMapRowMapper{
    private static boolean isMetadataSet = false;
    @Autowired
    private StepExecution stepExecution;
    @Autowired
    private String delimiter;

    private String metadata="";
    @Override
    public Map<String, Object> mapRow(ResultSet rs, int rowNum) throws SQLException {
        System.out.println("Inside custom row mapper "+this.getClass().getName());
        ResultSetMetaData rsmd = rs.getMetaData();

        int columnCount = rsmd.getColumnCount();
        Map<String, Object> mapOfColValues = createColumnMap(columnCount);
        for (int i = 1; i <= columnCount; i++) {
            String key = getColumnKey(JdbcUtils.lookupColumnName(rsmd, i));
            if(!this.isMetadataSet){
                if(i==columnCount){
                    metadata=metadata.concat(key);
                    break;
                }
                metadata=metadata.concat(key).concat(delimiter);
            }
            Object obj = getColumnValue(rs, i);
            mapOfColValues.put(key, obj);
        }
        if(!this.isMetadataSet){
            this.stepExecution.getJobExecution().getExecutionContext().put("metadata", this.metadata);
            this.isMetadataSet = true;
            System.out.println("Metadata retrieved is "+this.stepExecution.getJobExecution().getExecutionContext().get("metadata"));
        }

        //System.out.println("Metadata is "+this.metadata);
        return mapOfColValues;
    }
请查看我的作业配置

<batch:job id="ReportJob">
    <batch:step id="step1">
        <batch:tasklet transaction-manager="transactionManager">
            <batch:chunk reader="databaseItemReader" writer="flatFileItemWriter"
                processor="itemProcessor" commit-interval="100" />
        </batch:tasklet>
    </batch:step>
    <batch:listeners>
        <batch:listener ref="jobListener" />
    </batch:listeners>
</batch:job>


感谢您的快速响应。数据库读取器已经执行了查询并返回了结果集,因此我可以在不使用jdbcTemplate的情况下获取一些内容吗?我不能从读取器本身获取结果集吗?您需要创建一个自定义的
ItemReader
,将元数据提取到
ExecutionContext
中,以便它是一个可跨组件使用。Vishal如果不想再次运行查询,则需要自定义ItemReader并向ExecutionContext添加Michael提到的元数据。在writeHeader方法中使用此ExecutionContext。如果答案有帮助,请接受它,以便其他人也可以使用相同的方法。实际上,我尝试在rowmapper中获取元数据一次。但是只有在写下标题后才会调用。你能给我一些关于这个的示例吗?添加了一些示例代码,请检查单独的答案谢谢你的快速响应。我可以不使用jdbcTemplate获取一些内容吗?因为数据库读取器已经执行了查询并返回了结果集。我不能从reade获取结果集吗r本身。您需要创建一个自定义的
ItemReader
,将元数据提取到
ExecutionContext
中,以便跨组件提供元数据。Vishal如果您不想再次运行查询,则需要自定义ItemReader并向ExecutionContext添加Michael提到的元数据。使用此executioncontentxt在writeHeader方法中。如果答案帮助您,请接受它,这样其他人也可以使用相同的方法。实际上,我曾尝试在rowmapper中获取元数据。但这只有在写下标题后才调用。您能给我一些关于这方面的示例吗。添加了一些示例代码,请检查单独的答案