问题描述
假设我有一个 person 表。一个人可以拥有一到三个产品,它看起来像这样。
id person_id product price
1 person1 product3 1
2 person1 product2 2
3 person1 product1 10
4 person2 product1 11
5 person2 product2 14
我应该为每个人获取所有产品,然后对其进行处理(对价格进行映射,进行一些逻辑),然后将计算数据写入最终表,该表仅包含两个字段(person_id 和calculated_value,其中person_id 是键)
person_id calculated_value
person1 100
person2 111
person3 93
在这种情况下实现项目阅读器的最佳方法是什么?(获取每个人的所有产品并对其进行处理) 是否可以在项目阅读器中的一个查询中完成,或者我应该在项目处理器中为每个人进行额外的查询?
解决方法
这更像是一个设计问题,因此可能不适合 SO,但我会尽力提供帮助。通常,您应该针对步进处理器本身不检索数据而仅进行处理。相反,读者应该收集所有数据并在读取数据时对其进行映射,并呈现一个计算驱动的工作单元,然后可以对其进行处理并随后输出到任何需要的地方。
考虑到这一点...
是否可以在项目阅读器中的一个查询中完成 ^-- 如果这可以通过查询来完成,是的,您应该这样做。
此外,如果您需要基于查询中响应数据的编程干预/查找/映射,那么您可以从编程部分和现有的 Sql 读取器中创建一个复合读取器,以便您从 SQL 读取器读取您需要的字段和然后将这些转换为以编程方式丰富的作品单元,然后传递给处理器进行工作。如果您需要将多行有效地组合到一个工作单元中,请查看聚合项目阅读器方法。这是一个讨论以下内容的 SO:spring batch aggregate records from db as one single record
...或者我应该在项目处理器中为每个人做额外的查询? ^-- 您应该避免在处理器中收集/查询更多数据。虽然你可以做得很好,而且非常方便,但它不是每个框架获取更多数据的指定位置。最好将处理器设计为无状态引擎并且所有收集工作由读者负责。
,面向块的处理模型不适合这种聚合。正如 Gordon Linoff 在评论中所建议的那样,将这些数据存储在表中并让数据库进行计算会更容易、更有效。如果你真的想用 Spring Batch 来做,你可以分两步进行:
- 第 1 步:执行
select distinct(person_id) from table
以获取人员 ID 的不同值的 tasklet。此列表将传递到第二步。 - 第 2 步:面向块的步骤,其中读取器迭代人员 ID,处理器执行附加查询以获取产品并进行计算。此步骤的编写者可以根据需要编写聚合值。