我试图了解如何将spring batch的概念应用于我们的用例。
我们将不得不从数据库中读取数据并从中创建固定长度的平面文件。具体来说,数据库看起来将类似于此:
|---------| |---------|
| Person | 1----n | Address |
|---------| |---------|
1
|
n
|---------|
| Job |
|---------|
输出文件将类似于以下内容:
PERSON1HEADER
PERSON1INFORMATION
ADDRESS1.1
ADRRESS1.2
JOB1.1
PERSON1FOOTER#OFADDRESS2#OFJOB1
PERSON2HEADER
PERSON2INFORMATION
ADDRESS2.1
JOB2.1
JOB2.2
PERSON2FOOTER#OFADDRESS1#OFJOB2
我的第一个想法是创建一个工作,该工作开始于“ Person”步骤。然后,“人员”步骤将从数据库加载所有信息,并为每个人员开始更多的步骤,例如地址和工作步骤。
这个想法是在我无法在JavaConfig中创建的步骤之间建立某种父子连接。
当前的想法是创建一个自定义LineAggregator
,该自定义public class MyLineAggregator implements LineAggregator<Person> {
private Map<String, LineAggregator<Person>> aggregators;
@Override
public String aggregate(Person item) {
StringBuilder builder = new StringBuilder();
builder.append(aggregators.get("person").aggregate(item) + LINE_ENDING);
for(Address address : item.getAddress()) {
builder.append(aggregators.get("address").aggregate(address) + LINE_ENDING);
}
for(Job job : item.getJob()) {
builder.append(aggregators.get("job").aggregate(job) + LINE_ENDING);
}
return builder.toString();
}
public void setAggregators(Map<String, LineAggregator<Person>> aggregators) {
this.aggregators = aggregators;
}
}
为每个人创建所有行。我真的觉得应该有一种更清洁的方式来做到这一点。
我当前方法的POC:
@Bean
public FlatFileItemWriter<Person> itemWriter3(MyLineAggregator myLineAggregator) {
return new FlatFileItemWriterBuilder<Person>()
.name("flatfile")
.resource(new FileSystemResource("target/test-outputs/output.txt"))
.lineAggregator(myLineAggregator)
.build();
}
@Bean
public Step testStep(FlatFileItemWriter<Person> itemWriter3) {
RepositoryItemReader<Person> repoReader = new RepositoryItemReaderBuilder<Person>()
.repository(personRepo)
.sorts(Map.of("personId", Sort.Direction.ASC))
.saveState(false)
.methodName("findAll").build();
return stepBuilderFactory.get("testStep")
.<Person, Person>chunk(10)
.reader(repoReader)
.writer(itemWriter3)
.build();
}
作业配置:
Disposable scanSubscription = rxBleClient.scanBleDevices(
new ScanSettings.Builder()
// .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) // change if needed
// .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) // change if needed
.build()
// add filters if needed
)
.subscribe(
scanResult -> {
// Process scan result here.
Log.v(TAG,"Ble device address: " it.bleDevice.macAddress
},
throwable -> {
// Handle an error here.
}
);
// When done, just dispose.
scanSubscription.dispose();
companion object {
const val TAG = "your_tag_here"
}
任何想法都会受到赞赏
答案 0 :(得分:1)
您的PoC对我来说看起来不错,我认为您真的不需要在步骤之间创建父/子关系。如果要执行此操作,最接近的方法是使用FlowStep。
由于您的Userslist
已经抓住了他们的地址和职位,因此无需像使用driving query pattern那样对每个人的详细信息(地址和职位)进行其他查询。对于行聚合器来说也是一样,我将以相同的方式实现它。