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;
        ...
    }

間に 1 対多の関係はないため、未受信のニュースを取得するには、次のように取得できます。

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

私のユーザーベースは現在 28,000 人であり、ステップ 1 と 2 を として、ItemReaderステップ 3 と 4 を として設定しているため、Spring Batch を使用することにしましたItemWriter

問題は、最初の 2 つのステップにあります。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
)

編集:データ モデルに多対多の結合テーブルがないのは残念ですが、漠然とした 1 対多の関係を追加すると、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

上のカーソルは、探している正確なタプルを提供しませんが、最初のオブジェクトがユーザーで、2 番目のオブジェクトが未送信のニュース項目である Object[2] を取得します。おそらく、リーダーにアグリゲーターを記述して、いくつかの結果を組み合わせて必要なタプルにすることができます。

于 2016-06-30T23:26:54.613 に答える