Spring Batch机制相当新 - 我设法让它运行起来但我的业务逻辑似乎不适合作为Spring Batch工作。请允许我解释一下:
该工作负责向用户发送电子邮件,如下所示:
Set<News>
)Set<User>
)实体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>>
)获取用户集。
我可以做些什么来让我的读者返回一个用户组和他/她未接收的新闻集?我错过了什么?
非常感谢。如果您需要更多信息,请告诉我。
答案 0 :(得分: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
这也假设您在创建新新闻时,使用SENT_FLG = 'N'
预先填充USER_NEWS表。
如果情况不对,您可以这样做:
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],其中第一个对象是User,Second是未发送的新闻项。据推测,您可以在阅读器中编写聚合器,将多个结果组合到您想要的元组中。