JPA 各項目の最新インスタンスを選択する 質問する

JPA 各項目の最新インスタンスを選択する 質問する

会議エンティティがあるとします。各会議には出席者 1 名と会議の日付があります。会議テーブルには、出席者ごとに複数の会議があり、それぞれ日付が異なります。すべての出席者に対して最新の会議のみを選択する JPA クエリが必要です。たとえば、テーブルが次のようになっているとします。

Meeting ID | Attendee ID | Meeting Date
1          | 1           |  6/1/2011
2          | 2           |  6/1/2011
3          | 1           |  6/6/2011
4          | 3           |  6/6/2011

私の結果は

Meeting ID | Attendee ID | Meeting Date
2          | 2           |  6/1/2011
3          | 1           |  6/6/2011
4          | 3           |  6/6/2011

Postgres に対して JPA 2 を使用しています。会議には出席者との 1 対 1 のやり取りと、単純なタイムスタンプの日付があります。グループ化と max(blah) を実行し、自分自身に結合する必要があると思いますが、これに最適な方法がわかりません。

アップデート:一晩中これをいじっていましたが、まだこれに対する許容できる JPQL ソリューションが見つかりません。これまでにわかったことは次のとおりです。

select m from Meeting m 
where m.meetingDate in 
    ( select max(meet.meetingDate) 
      from Meeting meet group by meet.attendee )

出席者の部門によるフィルタリングなど、この質問とは関係のないさまざまな条件があります。これが機能する唯一の理由は、会議の日付を秒単位 (またはより細かい単位) で追跡しているため、2 つの会議がまったく同じ時間に開催される可能性が最小限であることです。2 つの会議が同時に開催される場合に備えて、各出席者の最後の会議のみを保持するように Java のいくつかの要素を配置していますが、これはかなりひどいソリューションです。すべてをクエリで取得するのはそれほど難しいことではないはずですが、まだ解決できていません。

アップデート2:SQL タグを追加するのは、SQL を使用してビューを作成し、そのビューにマップする JPA オブジェクトを作成する必要がある場合でも問題ないからです。

ベストアンサー1

SQL では、解決策は非常に簡単です。サブクエリを使用してテーブルを結合すると、各出席者の最新の会議が返されます。

select * from Meeting ALL
join ( select max(meetingDate) as newest, attendee
from Meeting group by attendee ) LATEST
on ALL.meetingDate = LATEST.newest AND ALL.attendee = LATEST.attendee

これは機能し、しかも高速です!

JPA の問題は、JPA (またはほとんどの実装) が結合のサブクエリを許可しないことです。最初に何がコンパイルされるか、そしてそれがいかに遅いかを試すのに数時間を費やした後、私は JPA が嫌いだと決めました。上記のようなソリューション (EXISTS (SELECT ..) や IN ( SELECT ..) など) は実行に時間がかかり、本来よりも桁違いに遅くなります。

機能するソリューションがあれば、JPA からそのソリューションにアクセスするだけで済みます。SQL には、まさにそれを実現するのに役立つ 2 つの魔法の言葉があります。

CREATE VIEW

そして、生活はずっとシンプルになります... そのようなエンティティを定義して使用するだけです。 注意: 読み取り専用です。

もちろん、そうすると JPA 純粋主義者から軽蔑されるので、純粋な JPA ソリューションをお持ちの方がいらっしゃいましたら、ぜひ私たちにお知らせください。

おすすめ記事