Spring Batch:如何为每个项目在数据库表中插入多个键值对

时间:2018-04-04 12:03:32

标签: spring hibernate jdbc spring-batch key-value

使用Spring Batch ItemProcessor处理一些XML文件之后。 ItemProcessor返回如下项目:

MetsModsDef
{
   int id;
   String title;
   String path;
   Properties identifers;
   ....
}

现在我需要将这些项目保存到数据库中,以便    (id,title,path)将进入"工作"表

和所有属性存储在"标识符"字段进入"键/值" -Table调用"标识符" (work,identitytype,identityValue)

我怎么能实现这个目标?

目前我正在使用CompositeItemWriter来拆分对象并将其写入两个表中,如下所示:

   public ItemWriter<MetsModsDef> MultiTableJdbcWriter(@Qualifier("dataSource") DataSource dataSource) {

    CompositeItemWriter<MetsModsDef> cWriter = new CompositeItemWriter<MetsModsDef>();

    JdbcBatchItemWriter hsqlWorkWriter = new JdbcBatchItemWriterBuilder()
        .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
        .sql("INSERT INTO work (id, title, path,enabled) VALUES (:id, :title,:path,1)" )
        .dataSource(dataSource)
        .build();

    JdbcBatchItemWriter hsqlIdentifierWriter = new JdbcBatchItemWriterBuilder()
        .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
        .sql("INSERT INTO identity (work, identitytype, identityValue) VALUES (:work, :identitytype, :identityValue)" )
        .dataSource(dataSource)
        .build();

    List<ItemWriter<? super MetsModsDef>> mWriter = new ArrayList<ItemWriter<? super MetsModsDef>>();
    mWriter.add(hsqlWorkWriter);
    mWriter.add(hsqlIdentifierWriter);
    cWriter.setDelegates(mWriter);

但这对于属性列表不起作用,因为(work,identitytype,identityValue)不是我的域对象MetModsDef的一部分,它只包含一个应该进入Identifier表的属性映射。

我在写入文件时找到了如何做的建议, 甚至使用Spring-Integration Read one record/item and write multiple records/items using spring batch的分割器模式 但是当我通过jdbc或hibernate写出来时,我仍然不确定如何实际做到这一点(我假设它会类似) 谢谢你的建议!

1 个答案:

答案 0 :(得分:0)

如果有人感兴趣:过了一段时间我想出了自己的解决方案: 我在互联网上找到了一个扩展HibernateItemWriter(用于hibernate写入):

Spring-Batch Multi-line record Item Writer with variable number of lines per record 但我不想扩展课程,所以我不得不提出自己的课程(基于我可以在互联网上研究的内容)。

我不确定它有多好,以及如何处理事务或回滚(可能不好)。但现在它是我唯一拥有的。所以如果你也需要一个,或者对如何改进它有意见。甚至有一个更好的。非常欢迎你。 我创建了自己的IdentifierListWriter,它为每个MetsModsDef项创建了类似于键/值对的对象(这里每个对称为“identitifier”),并使用从配置传递给它的JdbcBatchItemWriter identifierWriter将它们全部写出来

    public class IdentifierListWriter implements ItemWriter<MetsModsDef>
{
    private ItemWriter<Identifier>      _identifierWriter;

    public IdentifierListWriter ( JdbcBatchItemWriter<Identifier> identifierWriter )
    {
        _identifierWriter= identifierWriter;
    }

    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public void write(List<? extends MetsModsDef> items) throws Exception
    {
        // Main Table WRITER
        for ( MetsModsDef item : items )
        {
            ArrayList<Identifier> ids = new ArrayList<Identifier>();
            for(String key : item.getAllIds().stringPropertyNames())
            {
             ids.add(new Identifier(item.getAllIds().getProperty(key),
                     key, item.getId()));
            }
            _identifierWriter.write(ids);
      }
    }
}

在java配置中,我创建了两个jdbcBatchItemWriter Beans。一个用于“工作”表,一个用于“标识符”表。 IdentifierListWriter bean和CompositeItemWriter MultiTableJdbcWriter Bean使用它们来写出对象

 @Bean
@Primary
public ItemWriter<MetsModsDef> MultiTableJdbcWriter(@Qualifier("dataSource") DataSource dataSource) {

    IdentifierListWriter identifierListWriter = new IdentifierListWriter(identifierWriter(dataSource) );

    CompositeItemWriter cWriter = new CompositeItemWriter();
    cWriter.setDelegates(Arrays.asList(hsqlWorkWriter(dataSource),identifierListWriter));
    return cWriter;
}

@Bean
public JdbcBatchItemWriter<MetsModsDef> hsqlWorkWriter(@Qualifier("dataSource") DataSource dataSource) {
    return new JdbcBatchItemWriterBuilder<MetsModsDef>()
            .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
            .sql("INSERT INTO work (id, title, path,enabled) VALUES (:id, :title,:path,1)")
            .dataSource(dataSource)
            .build();

}

@Bean
public JdbcBatchItemWriter<Identifier> identifierWriter(@Qualifier("dataSource") DataSource dataSource) {
    return new JdbcBatchItemWriterBuilder()
            .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
            .sql("INSERT INTO identifier (identifier, type, work_id) VALUES ( :identifier, :type, :work)")
            .dataSource(dataSource)
            //.afterPropertiesSet()
            .build();
}

然后从Step:

调用multiTableJdbcWriter
   @Bean
public Step step1(ItemWriter<MetsModsDef> multiTableJdbcWriter) {
    return stepBuilderFactory.get("step1")
            .<StreamSource, MetsModsDef>chunk(1)
            .reader(new MetsModsReader())
            .processor(metsModsFileProcessor())
            .writer(multiTableJdbcWriter)