3

特定の日付以降に作成された行を持つテーブルを特定するために、基本的にいくつかのテーブルから選択する SQL クエリを作成しました。私のSQLは次のようになります。

SELECT widget_type FROM(
  SELECT 'A' as widget_type
  FROM widget_a
  WHERE creation_timestamp > :cutoff
  UNION
  SELECT 'B' as widget_type
  FROM widget_b
  WHERE creation_timestamp > :cutoff
) types
GROUP BY widget_type
HAVING count(*)>0

これはSQLではうまく機能しますが、JPAはユニオンを使用して「クラスごとのテーブル」ポリモーフィッククエリを実行できますが、JPQLはクエリでユニオンをサポートしていないことが最近わかりました。そのため、JPA に同じことを達成するために使用できる代替手段があるかどうか疑問に思っています。

実際には、2 つだけでなく 12 個のテーブルに対してクエリを実行することになるため、個別のクエリを実行することは避けたいと考えています。また、移植性の理由から、ネイティブ SQL クエリを実行することも避けたいと思います。

上記にリンクした質問では、widget_a と widget_b にマップされるエンティティが同じ継承ツリーの一部であるかどうかを尋ねられました。はい、そうです。ただし、基本クラスから選択した場合、子エンティティごとに異なる文字列定数を指定する方法はないと思いますよね? 私が提供する文字列の代わりにエンティティのクラス名を選択できれば、それも私の目的に役立つかもしれません。しかし、それが可能かどうかもわかりません。考え?

4

2 に答える 2

13

私はもう少し検索を行い、私の目的を完全に果たす JPA の (一見あいまいな) 機能を見つけました。私が見つけたのは、JPA 2 には、次のtypeようにポリモーフィック クエリを特定のサブクラスに制限できるキーワードがあることです。

SELECT widget
FROM BaseWidget widget
WHERE TYPE(widget) in (WidgetB, WidgetC)

JPA (または少なくとも JPA 実装としての Hibernate) を使用するとtype、制約だけでなく選択リストでも使用できることがわかりました。これは、私のクエリが最終的に次のようになったおおよそのものです。

SELECT DISTINCT TYPE(widget)
FROM BaseWidget widget
WHERE widget.creationTimestamp > :cutoff

そのクエリは、Classオブジェクトのリストを返します。私の元のクエリは文字列リテラルを選択していました。これは、SQL で行った可能性があることに最も近いからです。Class私の場合、実際には選択が望ましいです。しかし、エンティティの型に基づいて定数を選択したい場合は、それがOracle のドキュメントcaseでステートメントを説明するために使用されている正確なシナリオです。

SELECT p.name
CASE TYPE(p)
  WHEN Student THEN 'kid'
  WHEN Guardian THEN 'adult'
  WHEN Staff THEN 'adult'
  ELSE 'unknown'
END
FROM Person p
于 2013-03-05T06:45:45.910 に答える
0

一部の JPA プロバイダーは UNION をサポートしていますが、

http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/JPQL#UNION

ただし、クエリは非常に複雑で、オブジェクト指向ではないように見えるため、ネイティブ SQL クエリを使用するのがおそらく最善です。

于 2013-02-26T14:39:42.490 に答える