java - 如何使用spring boot batch在不同的类中赋予不同的Bean
问题描述
我正在尝试从 SQL 服务器加载数据,应用一些转换并使用 spring 批处理调度程序将其放入 CSV。当一切都在同一个班级时,一切都很好。
这是我的代码:
package com.abc.tools.bootbatch;
@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@Autowired
public DataSource dataSource;
private static final String qry = "select top 20 colA, colB, colC from ABC";
private Resource outputResource = new FileSystemResource("output/outputData.csv");
@Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(driver_class);
dataSource.setUrl("db_url");
dataSource.setUsername(usr);
dataSource.setPassword(pwd);
return dataSource;
}
@Bean
ItemReader<Trade> reader() {
JdbcCursorItemReader<Trade> databaseReader = new JdbcCursorItemReader<>();
databaseReader.setDataSource(dataSource);
databaseReader.setSql(qry);
databaseReader.setRowMapper(new BeanPropertyRowMapper<>(Trade.class));
return databaseReader;
}
@Bean
public TradeProcessor processor() {
return new TradeProcessor();
}
@Bean
public FlatFileItemWriter<Trade> writer()
{
//Create writer instance
FlatFileItemWriter<Trade> writer = new FlatFileItemWriter<>();
//Set output file location
writer.setResource(outputResource);
//All job repetitions should "append" to same output file
writer.setAppendAllowed(true);
//Name field values sequence based on object properties
writer.setLineAggregator(new DelimitedLineAggregator<Trade>() {
{
setDelimiter(",");
setFieldExtractor(new BeanWrapperFieldExtractor<Trade>() {
{
setNames(new String[] { "colA", "colB", "colC" });
}
});
}
});
return writer;
}
@Bean
public Step step1() {
return stepBuilderFactory.get("step1").<Trade, Trade> chunk(10)
.reader(reader())
.processor(processor())
.writer(writer())
.build();
}
@Bean
public Job exportUserJob() {
return jobBuilderFactory.get("exportUserJob")
.incrementer(new RunIdIncrementer())
.flow(step1())
.end()
.build();
}
}
当我在不同的类中分离处理、加载和数据读取时,使用自动装配它可以正常工作,除非我使用批处理作业。在使用批处理作业时,它会在实例化数据库时出错。所以我删除了自动连线并尝试做这样的事情:
@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@Autowired
public DBConfig dbConfig;
public DataConnection dataconnection=new DataConnection();
DataReader reader=new DataReader();
TradeProcessor processor=new TradeProcessor();
FlatFileWriter flatFileWriter=new FlatFileWriter();
DataSource ds=dataconnection.getDataSource(dbConfig);
@Bean
public Step step1() {
return stepBuilderFactory.get("step1").<Trade, Trade> chunk(10)
.reader(reader.reader(ds))
.processor(processor.processor())
.writer(flatFileWriter.writer())
.build();
}
@Bean
public Job exportUserJob() {
return jobBuilderFactory.get("exportUserJob")
.incrementer(new RunIdIncrementer())
.flow(step1())
.end()
.build();
}
}
这给出了 Failed to initialize BatchConfiguration
org.springframework.beans.factory.BeanCreationException:创建名为“batchConfiguration”的bean时出错
我想我错过了一些东西来汇总这一切。我是 Spring 新手,感谢任何帮助
解决方案
在您的第一个示例中,您正在自动装配一个数据源并在同一个类中声明一个数据源 bean,这是不正确的。在第二个示例中,您可以根据需要在作业配置中使用数据源DBConfig
导入并自动装配数据源,而不是自动装配。@Import(DBConfig.class)
这是一个典型的配置:
@Configuration
public class DBConfig {
@Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(driver_class);
dataSource.setUrl("db_url");
dataSource.setUsername(usr);
dataSource.setPassword(pwd);
return dataSource;
}
}
@Configuration
@EnableBatchProcessing
@Import(DBConfig.class)
public class BatchConfiguration {
@Bean
ItemReader<Trade> reader(DataSource datasource) {
// use datasource to configure the reader
}
}
由于您使用 Spring Boot,您可以删除DBConfig
该类,根据需要在application.properties
文件中配置数据源,数据源将自动注入到您的BatchConfiguration
.
推荐阅读
- camel-http - Restlet 错误:“无法运行以下服务器端任务:sun.net.httpserver.ServerImpl$Exchange@56d26222”
- node.js - 如何在同一个 handler.js 文件中调用另一个 AWS 函数?并附加查询字符串参数?
- react-native - 如何添加填充或更改底部标签 RNN 的高度
- mysql - SQL query to get data between 2 date valid time table
- java - JavaFX 1.8 中的定时器(时钟)
- node.js - 根据用户选择在持久和非持久会话之间切换
- laravel - Laravel - 传递给 App\Exports\UserresponseExport::__construct() 的参数 1 必须是字符串类型
- java - Jaspersoft Studio - 如何创建自定义函数来增加/减少条形图中条形的宽度?
- javascript - 未读取图像数组
- amazon-web-services - 使用函数将多个查询从 Redshift 卸载到 Amazon S3