1

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

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

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

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

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

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

这里的最佳做法是什么?

谢谢!

4

2 回答 2

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 来了解还有更多的实体要提交给数据库。

希望能帮助到你...

于 2012-10-14T15:52:42.803 回答
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用来持久化你的 eneities 来代替persist.

于 2012-10-14T07:30:25.867 回答