ItemProcessor既需要修改工作实体,也需要创建新引用的实体

时间:2012-10-13 21:11:44

标签: spring hibernate jpa spring-batch

使用spring-batch和JPA(由hibernate提供)。

我有一个执行以下操作的步骤:

  • 从DB(客户端实体)
  • 读取所有客户端
  • 使用第三方的数据增强它们。 ItemProcessor转到第三方数据源,获取它存储在客户端实体本身(其字段)中的一些数据,但也会带来更多数据,这些数据存储为不同的实体(ClientSale),而Client具有List的属性,该属性由映射到多对一。
  • 修改后的实体(客户端)和新实体(ClientSale)需要存储在DB中。

读者部分是直截了当的,对于作者我使用了JPAItemWriter。在处理阶段,我尝试更新字段,创建新字段并将它们添加到客户端列表并返回客户端,希望编写器将引用的对象和客户端本身写入数据库。

相反,我收到一条错误,指出ID中不存在ID为#123213213的ClientSale。

如何克服这个问题?我应该从处理器(客户端+所有ClientSale)返回对象列表(不同类型)吗? JPAItemWriter可以处理对象列表吗?另一个问题是我将不得不手动更新ClientSale实体中的client_id,而不是将它们添加到列表中并使用hibernate来理解它们之间的关系以及谁指向哪里..

这里的最佳做法是什么?

谢谢!

2 个答案:

答案 0 :(得分:1)

好的..这是我最后根据一切所做的事情: 我创建了一个MultiEntityItemWriter,它可以作为项目接收列表(在这种情况下,它会打开它并将所有元素写入委派的ItemWriter。

代码:

public class MultiEntityItemWriter implements ItemWriter<Object>{

private ItemWriter<Object> delegate;

@Override
public void write(List<? extends Object> items) throws Exception {
    List<Object> toWrite = new ArrayList<>();

    for (Object item : items) {
        if (item instanceof Collection<?>) {
            toWrite.addAll((Collection<?>)item);
        } else {
            toWrite.add(item);
        }
    }
    delegate.write(toWrite);
}


public ItemWriter<Object> getDelegate() {
    return delegate;
}

public void setDelegate(ItemWriter<Object> delegate) {
    this.delegate = delegate;
}

}

现在,我的ItemProcessor可以输出一个列表,其中包含要写入的所有实体,我不需要依赖JPA来了解有更多实体要提交给数据库。

希望它有所帮助...

答案 1 :(得分:0)

我认为您正试图一步完成多个步骤。尝试找到一种方法,将工作定义为两步而不是一步。

    <batch:job id="MyJob" incrementer="incrementer" job-repository="jobRepository">
     <batch:step id="step1" next="step2">
       <tasklet >
          <chunk reader="reader1" 
                     writer="writer1" 
                     processor="processor1" 
                     commit-interval="10" />
       </tasklet>
     </batch:step>
     <batch:step id="step2">
       <tasklet >
          <chunk reader="reader2" 
                     writer="writer2" 
                     processor="processor2" 
                     commit-interval="10" />
       </tasklet>
     </batch:step>
    </batch:job>

如果需要,请使用适当的缓存以获得最佳性能。

编辑:

在您的项目编写者中,请确保您使用的是entityManager/session第一个数据源。同时使用merge代替persist来保持你的能量。