0

Spring Batch 机制相当新——我设法让它启动并运行,但我的业务逻辑似乎不适合作为 Spring Batch 工作。请允许我解释一下:

该工作负责向用户发送电子邮件,如下所示:

  1. 获取满足特定条件的新闻项目集 ( Set<News>)
  2. 获取尚未收到新闻项目之一的用户集 ( Set<User>)
  3. 对于每个用户,为用户未收到的每个新闻发送一封电子邮件。
  4. “标记”已收到/已收到新闻的用户。

实体bean定义如下:

    @Entity
    public class News {
        ...
        // ID with a sequence generator (more recent news have a higher ID value)
        private Integer id;
        ...
    }

    @Entity
    public class User {
        ...
        // last received news;
        private Integer lastReceivedNewsId;
        ...
    }

两者之间没有一对多的关系,因此为了检索未收到的新闻,可以按如下方式检索:

SELECT n FROM db.news n 
JOIN User u on n.id > u.lastReceivedNewsId; 

我决定使用 Spring Batch,因为我的用户群目前为 28,000 并且还在增加,将步骤 1 和 2 设置为 ,将ItemReader步骤 3 和 4 设置为ItemWriter.

问题在于前两个步骤:我决定使用JpaPagingItemReader<T>我的读者,但不幸的是它非常严格,以至于我只能指定一个查询,而不会更改将结果集映射到其他东西。在我的示例中,我首先需要获取一组新闻,然后根据收到的新闻 ( Tuple<User, Set<News>>) 查询数据库以获取一组用户。

我该怎么做才能让我的读者返回一组用户和他/她未收到的新闻集?我错过了什么?

非常感激。如果您需要更多信息,请告诉我。

4

1 回答 1

0

如果您可以使用 Hibernate,我建议您查看HibernateCursorItemReader. 我将对你的数据模型做一些假设,所以希望这足够接近有用......

USER: USER_ID
NEWS: NEWS_ID, CONDITION_COL
USER_NEWS: USER_ID, NEWS_ID, SENT_FLG

假设您的持久性对象之间存在关系,您可以将 HQL 编写为如下所示:

select un from UserNews un
inner join fetch un.news news
inner join fetch un.user user
where un.sentFlag = false
and news.condition = :injectCondition

这还假设当您创建一个新的新闻项目时,您使用 预填充 USER_NEWS 表SENT_FLG = 'N'

如果这不是真的,你可以这样做:

INSERT INTO USER_NEWS (USER_ID, NEWS_ID, SENT_FLG)
SELECT U.USER_ID, N.NEWS_ID, 'N' SENT_FLG
FROM USER U, NEWS N
WHERE NOT EXISTS (
  SELECT 1 
  FROM USER_NEWS UN
  WHERE     UN.USER_ID = U.USER_ID
        AND UN.NEWS_ID = N.NEWS_ID
)

编辑:你的数据模型中没有多对多连接表太糟糕了,但是如果你添加一个模糊的一对多关系,Hibernate 仍然可以提供帮助:

@OneToMany
@JoinColumnsOrFormulas({
    @JoinColumnOrFormula(formula=@JoinFormula(value="(SELECT n.id FROM News n)", referencedColumnName="id"))
})
private Set<News> newsItems;

然后您的 HQL 查询将如下所示:

from User u
left join fetch u.newsItems n
where n.id > u.lastReceivedNewsId

如果这不起作用,还有一个不太漂亮的选项,您可以在其中编写这样的驾驶查询:

select u, n from User u, News n where n.id > u.lastReceivedNewsId
order by u.id, n.id

上面的光标不会为您提供您正在寻找的确切元组,但您会得到 Object[2] 其中第一个对象是用户,第二个是未发送的新闻项目。大概,然后您可以在阅读器中编写一个聚合器,将多个结果组合成您想要的元组。

于 2016-06-30T23:26:54.613 回答