问题
I need to denormalize data stored into a relational database.
There are too much tables linked between each others, and it's not possible to build a single query to get every data.
Here a simplified situation:
+-------------+ +-------------+
| | 1 N | |
| Unitat +-----------> Authors |
| | | |
+-------------+ +-------------+
Up to now I've build an step that is getting all Unitat rows:
@Bean
public ItemReader<Unitat> reader() {
String sql = "select * from unitat";
JdbcCursorItemReader<Unitat> jdbcCursorItemReader = new JdbcCursorItemReader<>();
jdbcCursorItemReader.setDataSource(this.dataSource);
jdbcCursorItemReader.setSql(sql);
jdbcCursorItemReader.setVerifyCursorPosition(false);
jdbcCursorItemReader.setRowMapper(new UnitatRowMapper());
return jdbcCursorItemReader;
}
The RowMapper is:
public class UnitatRowMapper implements RowMapper<Unitat> {
private static final String ID_COLUMN = "id";
//...
@Override
public Unitat mapRow(ResultSet resultSet, int numRow) throws SQLException {
Unitat unitat = new Unitat();
unitat.setId(resultSet.getString(ID_COLUMN));
//...
return unitat;
}
}
Here my processor. It's only engaged to populate fields into a UnitatDenormalized object:
@Component
public class UnitatMappingItemProcessor implements ItemProcessor<Unitat, UnitatDenormalized> {
@Override
public UnitatDenormalized process(Unitat unitat) throws Exception {
UnitatDenormalized denormalized = new UnitatDenormalized();
denormalized.setId(unitat.getId());
//denormalized.set...()
return denormalized;
}
}
Here my current step and job configuration:
@Bean
public Step step(
ItemReader<Unitat> mssqlItemReader,
UnitatMappingItemProcessor processor,
SolrItemWriter solrItemWriter
) {
return this.stepBuilderFactory
.get("unitat")
.<Unitat, UnitatDenormalized>chunk(100)
.reader(mssqlItemReader)
.processor(processor)
.writer(solrItemWriter)
.build();
}
@Bean
public Job job(Step step) {
Job job = this.jobBuilderFactory.get("job1")
.flow(step)
.end()
.build();
return job;
}
How could I get authors and merge them to previously obtained unitat?
When and how could I perform next code?
// Here would I need to populate `authors`:
denormalized.addAutors(...);
denormalized.addAutors(...);
I hope I've explained so well...
回答1:
You can use the driving query pattern. The idea is to issue a request in your item processor to enrich items.
In your case, the query would fetch authors of the current unitat item and set them on the denormalized item before returning it.
来源:https://stackoverflow.com/questions/64888740/spring-batch-working-with-several-entities-and-merge-them