繁体   English   中英

从spring批处理ItemProcessor返回多个项目

[英]Return multiple items from spring batch ItemProcessor

我正在编写一个Spring批处理作业,在我的一个步骤中,我有以下处理器代码:

@Component
public class SubscriberProcessor implements ItemProcessor<NewsletterSubscriber, Account>, InitializingBean {

    @Autowired
    private AccountService service;

    @Override public Account process(NewsletterSubscriber item) throws Exception {
        if (!Strings.isNullOrEmpty(item.getId())) {
            return service.getAccount(item.getId());
        }
        // search with email address
        List<Account> accounts = service.findByEmail(item.getEmail());
        checkState(accounts.size() <= 1, "Found more than one account with email %s", item.getEmail());
        return accounts.isEmpty() ? null : accounts.get(0);
    }

    @Override public void afterPropertiesSet() throws Exception {
        Assert.notNull(service, "account service must be set");
    }
}

上面的代码有效,但我发现有一些边缘情况,每个NewsletterSubscriber允许有多个Account 所以我需要删除状态检查并将多个Account传递给项目编写者。

我找到的一个解决方案是更改ItemProcessorItemWriter以处理List<Account>类型而不是Account但这有两个缺点:

  • 由于编写器中的嵌套列表,代码和测试更加难以编写和维护
  • 最重要的是,多个Account对象可以写在同一个事务中,因为给写入者的列表可能包含多个帐户,我想避免这种情况。

有没有办法,可能使用一个监听器,或者更换一些弹簧批处理使用的内部组件以避免处理器中的列表?

更新

我已经在春季Jira上为这个问题打开了一个问题。

我期待到isCompletegetAdjustedOutputs的方法FaultTolerantChunkProcessor被标记为扩展点SimpleChunkProcessor ,看看我是否能以某种方式使用它们来实现我的目标。

任何提示都是受欢迎的。

Item Processor接受一件事,并返回一个列表

MyItemProcessor implements ItemProcessor<SingleThing,List<ExtractedThingFromSingleThing>> {
    public List<ExtractedThingFromSingleThing> process(SingleThing thing) {
    //parse and convert to list
    }
}

将下游作者包裹起来以解决问题。 这样,这个编写器下游的东西不必使用列表。

@StepScope
public class ItemListWriter<T> implements ItemWriter<List<T>> {
    private ItemWriter<T> wrapped;

    public ItemListWriter(ItemWriter<T> wrapped) {
        this.wrapped = wrapped;
    }

    @Override
    public void write(List<? extends List<T>> items) throws Exception {
        for (List<T> subList : items) {
            wrapped.write(subList);
        }
    }
}

没有办法在Spring Batch中每次调用返回多个ItemProcessor而没有深入杂草。 如果您真的想知道ItemProcessorItemWriter之间的关系退出( 不推荐 ),请查看ChunkProcessor接口的实现。 虽然简单的情况( SimpleChunkProcessor )并没有那么糟糕,但如果你使用任何容错逻辑(通过FaultTolerantChunkProcessor跳过/重试),它会非常快速。

一个更简单的选择是将此逻辑移动到ItemReader ,在返回项目之前执行此丰富。 在返回项目之前,在您执行服务查找的自定义ItemReader实现中包装您正在使用的任何ItemReader 在这种情况下,您不会从阅读器返回NewsletterSubscriber ,而是根据之前的信息返回一个Account

您返回的不是返回帐户,而是创建AccountWrapper或Collection。 作家显然必须考虑到这一点:)

您可以使用变换器将Pojo(Pojo对象从文件)转换为您的实体通过制作以下代码:

public class Intializer {

public static LGInfo initializeEntity() throws Exception {
    Constructor<LGInfo> constr1 = LGInfo.class.getConstructor();
    LGInfo info = constr1.newInstance();
    return info;
}
}

并在你的项目处理器

public class LgItemProcessor<LgBulkLine, LGInfo> implements ItemProcessor<LgBulkLine, LGInfo> {

private static final Log log = LogFactory.getLog(LgItemProcessor.class);

@SuppressWarnings("unchecked")
@Override
public LGInfo process(LgBulkLine item) throws Exception {
    log.info(item);
    return (LGInfo) Intializer.initializeEntity();
}

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM