使用弹簧批处理读取一个记录/项目并写入多个记录/项目
Posted
技术标签:
【中文标题】使用弹簧批处理读取一个记录/项目并写入多个记录/项目【英文标题】:Read one record/item and write multiple records/items using spring batch 【发布时间】:2011-12-15 05:14:37 【问题描述】:我进行了一些搜索,但找不到任何示例/示例。
我需要读取一个表(输入)中的地理坐标,并对其进行处理以生成与坐标相关联的 POI。因此,一个地理坐标将导致一个或多个 POI 需要插入到另一个表(输出)中。
我目前正在使用 JdbcCursorItemReader 和 JdbcBatchItemWriter 来读取一项/记录并写入一项/记录。还有一个 ItemProcessor 可以为给定的地理坐标生成 POI。
自定义 JdbcBatchItemWriter 是否可以帮助我实现这一目标?
有什么想法吗? TIA。
【问题讨论】:
【参考方案1】:我通过扩展 Writer 类(在我的例子中为 HibernateItemWriter)来做到这一点。我看到一个答案描述了如何使用“分离器”。如果有人有一个工作示例,说明在使用 spring-boot-starter-parent 的环境中如何工作,我很乐意看到它。对于我正在做的事情(从单个记录创建列表),如果 Spring 提供了一个处理列表列表的写入方法,那将会容易得多。
这是我如何扩展 Writer 以处理读取/处理的每一行的多次写入:Spring-Batch Multi-line record Item Writer with variable number of lines per record
【讨论】:
【参考方案2】:您真正要寻找的是Splitter 模式:
这是Spring Integration中的定义方式:
Splitter 是一种 Message Endpoint,其职责是从其输入通道接受一条消息,将该消息拆分为多个消息,然后将每个消息发送到其输出通道。这通常用于将“复合”有效负载对象划分为一组包含细分有效负载的消息。
配置极其简单:
<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 Support => jdbc:inbound-channel-adapter
/ jdbc:outbound-channel-adapter
和上面的拆分器来实现您想要的和......简单。
【讨论】:
只是好奇,restart 是否也适用于 spring 集成?或者换句话说,spring 集成只是一个薄的可插拔模块吗? 你绝对可以做 rerun vs restart (这是一个哲学讨论,因为 rerun 更干净:)。但是,如果您想在 Spring Batch(瘦可插拔模块)中使用它,您可以。尽管对于@user977505 的情况,单独使用 Spring Integration 和可能的一些 SB 组件(或没有)就可以了。 感谢您的回复。我会试一试并更新线程。 有人做过吗?或者有代码的链接?我查看了一些 spring 集成文档,但除了提到它是可能的之外找不到太多@Splitter
注释去哪儿了?【参考方案3】:
如果您只想将项目分散到不同的作者(读取重复输出),您可以使用现有的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,别忘了register the delegates as ItemStreams(这样 spring batch 会为你打开/关闭它们)
【讨论】:
谢谢迈克尔。我继续寻找答案,并或多或少地找到了相同的解决方案。我的项目处理器当前正在生成单个项目,但我可以修改它以返回项目列表。我计划使用单个编写器并将多个相同类型的项目写入表中。我会试一试,看看是否适合我。 这对我有用。我使用了一个处理器,该处理器返回项目列表和上面建议的作者。但是我使用带有批量更新的普通 jdbc 模板将项目插入数据库。关键部分是 'List项目'。我不熟悉这个符号,并试图从列表中读取项目。再次感谢您的帮助。以上是关于使用弹簧批处理读取一个记录/项目并写入多个记录/项目的主要内容,如果未能解决你的问题,请参考以下文章
使用存储过程从 sql server 快速读取百万条记录,并使用 java 和 spring boot 将其写入 csv