使用 Spring Batch 读取一条记录/项目并写入多条记录/项目

发布于 2024-12-11 18:10:40 字数 294 浏览 2 评论 0原文

我做了一些搜索,但找不到任何示例/示例。

我有一个要求,从一个表(输入)读取地理坐标,进行处理以生成与坐标关联的 POI。因此,一个地理坐标将产生一个或多个 POI,需要将其插入到另一个表(输出)中。

我目前正在使用 JdbcCursorItemReader 和 JdbcBatchItemWriter 读取一项/记录并写入一项/记录。还有一个 ItemProcessor,可以为给定的地理坐标生成 POI。

自定义 JdbcBatchItemWriter 可以帮助我实现这一目标吗?

有什么想法吗? TIA。

I did some searching but couldn't find any sample/example.

I've a requirement where geo coordinates from one table (input) are read, processed to generate POI's associated to coordinate. So one geo coordinate will result in one or more POI's that needs to be inserted into another table (output).

I'm currently using a JdbcCursorItemReader and JdbcBatchItemWriter to read one item/record and write one item/record. There is also an ItemProcessor that generates the POI's for a give geo coordinate.

Does a custom JdbcBatchItemWriter help me achieve this?

Any ideas? TIA.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

有木有妳兜一样 2024-12-18 18:10:41

我有一个类似的案例,我可以使用以下可重用代码解决它:

@Slf4j
public class ListItemWriter<T> implements ItemWriter<List<T>> {

  private ItemWriter<T> delegate;

  @Setter private int chunkSize = 0;

  public ListItemWriter(ItemWriter<T> delegate) {
    this.delegate = delegate;
  }

  @Override
  public void write(List<? extends List<T>> items) throws Exception {
    if (chunkSize == 0) {
      chunkSize = items.size();
    }
    List<T> allItems = items.stream().flatMap(Collection::stream).collect(Collectors.toList());
    log.info("writing {} items", allItems.size());
    List<List<T>> partitions = ListUtils.partition(allItems, chunkSize);
    for (List<T> partition : partitions) {
      delegate.write(partition);
    }
  }
}

读者:A
处理器:A->列表
写入器:new ListItemWriter(ItemWriterForB)

I had a similar case and i could solve it with the following reusable code:

@Slf4j
public class ListItemWriter<T> implements ItemWriter<List<T>> {

  private ItemWriter<T> delegate;

  @Setter private int chunkSize = 0;

  public ListItemWriter(ItemWriter<T> delegate) {
    this.delegate = delegate;
  }

  @Override
  public void write(List<? extends List<T>> items) throws Exception {
    if (chunkSize == 0) {
      chunkSize = items.size();
    }
    List<T> allItems = items.stream().flatMap(Collection::stream).collect(Collectors.toList());
    log.info("writing {} items", allItems.size());
    List<List<T>> partitions = ListUtils.partition(allItems, chunkSize);
    for (List<T> partition : partitions) {
      delegate.write(partition);
    }
  }
}

Reader: A
Processor: A -> List<B>
Writer: new ListItemWriter(ItemWriterForB)

高跟鞋的旋律 2024-12-18 18:10:40

您真正要寻找的是 Splitter 模式:

在此处输入图像描述

以下是它在 Spring Integration

Splitter 是一种消息端点,其职责是从其输入通道接受消息,将该消息拆分为多个消息,然后将每个消息发送到其输出通道。这通常用于将“复合”有效负载对象划分为一组包含细分有效负载的消息。

配置非常简单:

<channel id="inputChannel"/>

<splitter id="splitter" 
  ref="splitterBean" 
  method="split" 
  input-channel="inputChannel" 
  output-channel="outputChannel" />

<channel id="outputChannel"/>

<beans:bean id="splitterBean" class="sample.PojoSplitter"/>

或者您可以使用注释:

@Splitter
List<LineItem> extractItems(Order order) {
    return order.getItems()
}

您当然可以编写自己的JdbcBatchItemWriter 如果感觉更简单的话。然而 Spring Integration 已经为你做到了。

您可以使用 Spring Integration JDBC 支持 => jdbc:inbound-channel-adapter / jdbc:outbound-channel-adapter 和上面的分离器来实现你想要的和..简单性。

What you are really looking for is called a Splitter pattern:

enter image description here

Here is how it is defined in Spring Integration:

A Splitter is a type of Message Endpoint whose responsibility is to accept a Message from its input channel, split that Message into multiple Messages, and then send each of those to its output channel. This is typically used for dividing a "composite" payload object into a group of Messages containing the sub-divided payloads.

Configuration is extremely simple:

<channel id="inputChannel"/>

<splitter id="splitter" 
  ref="splitterBean" 
  method="split" 
  input-channel="inputChannel" 
  output-channel="outputChannel" />

<channel id="outputChannel"/>

<beans:bean id="splitterBean" class="sample.PojoSplitter"/>

Or you can use annotations:

@Splitter
List<LineItem> extractItems(Order order) {
    return order.getItems()
}

You can of course write your own JdbcBatchItemWriter if it feels simpler. However Spring Integration already does it for you.

You can use Spring Integration JDBC Support => jdbc:inbound-channel-adapter / jdbc:outbound-channel-adapter and the above splitter to achieve what you want and.. simplicity.

妄司 2024-12-18 18:10:40

如果您只想将项目传播给不同的作者(读取重复的输出),您可以使用现有的 CompositeItemWriter

但我不确定您的处理器是否会生成不同的项目类型,或者您是否想将一种复杂项目类型的内容传播给多个编写器,对于这些情况,您可以对 multiline-record-writer

public class MultiOutputItemWriter implements ItemWriter<Object> {

private JdbcBatchItemWriter<ClassFoo> delegateFoo;
private JdbcBatchItemWriter<ClassBar> delegateBar;

public void write(List<? extends Object> items) throws Exception {
       // if you have different types of items
       // check Object Class
       // add to new List<Classfoo>
       // call delegate e.g. delegateFoo.write(List with ClassFoo);
       //
       // or if you have complex objects
       // same procedure as above, but with
       // add to new List<Classfoo> with item.getClassFoo
 }
}

如果您使用 FlatFileItemWriter,请不要忘记将委托注册为 ItemStreams (因此 Spring Batch 将打开/为您关闭它们)

if you just want to spread the items to different writers (read duplicate output) you can use the existing CompositeItemWriter

but i'm not sure if your processor will produce different item types or if you want to spread the content of one complex item type to multiple writers, for those cases you can use a slightly changed version for a multiline-record-writer question

public class MultiOutputItemWriter implements ItemWriter<Object> {

private JdbcBatchItemWriter<ClassFoo> delegateFoo;
private JdbcBatchItemWriter<ClassBar> delegateBar;

public void write(List<? extends Object> items) throws Exception {
       // if you have different types of items
       // check Object Class
       // add to new List<Classfoo>
       // call delegate e.g. delegateFoo.write(List with ClassFoo);
       //
       // or if you have complex objects
       // same procedure as above, but with
       // add to new List<Classfoo> with item.getClassFoo
 }
}

if you use FlatFileItemWriter, do not forget to register the delegates as ItemStreams (so spring batch will open/close them for you)

半世晨晓 2024-12-18 18:10:40

我通过扩展 Writer 类(在我的例子中是 HibernateItemWriter)来做到这一点。我看到一个答案描述了如何使用“分离器”。如果有人有一个工作示例,说明如何在使用 spring-boot-starter-parent 的环境中工作,我很乐意看到它。对于我正在做的事情(从单个记录创建列表),如果 Spring 提供一个处理列表列表的写入方法,那么会容易得多。

以下是我如何扩展 Writer 以处理读取/处理的每​​一行的多次写入: Spring-Batch 多行记录项编写器,每条记录的行数可变

I did this by extending the Writer class (in my case HibernateItemWriter). I see one answer describes how to use a 'splitter'. If anyone has a working example of how that might work in an environment using the spring-boot-starter-parent, I would love to see it. For what I am doing (creating a List from a single record) it would be so much easier if Spring provided a write method that handled a List of Lists.

Here is how I extended the Writer to handle multiple writes for every line read/processed: Spring-Batch Multi-line record Item Writer with variable number of lines per record

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文