62

休止状態を使用してユニオン クエリを実装するには、どのような代替手段が必要ですか? 現時点では、休止状態がユニオンクエリをサポートしていないことはわかっています。現在、ユニオンを作成する唯一の方法は、ビューテーブルを使用することです。

もう1つのオプションはプレーンなjdbcを使用することですが、この方法では、すべての例/基準クエリのグッズと、休止状態がテーブル/列に対して実行する休止状態のマッピング検証が失われます。

4

9 に答える 9

76

あなたが使うことができますid in (select id from ...) or id in (select id from ...)

たとえば、機能しない代わりに

from Person p where p.name="Joe"
union
from Person p join p.children c where c.name="Joe"

あなたができる

from Person p 
  where p.id in (select p1.id from Person p1 where p1.name="Joe") 
    or p.id in (select p2.id from Person p2 join p2.children c where c.name="Joe");

ただし、少なくともMySQLを使用すると、後でパフォーマンスの問題が発生します。代わりに、2つのクエリで貧乏人の結合を行う方が簡単な場合があります。

// use set for uniqueness
Set<Person> people = new HashSet<Person>((List<Person>) query1.list());
people.addAll((List<Person>) query2.list());
return new ArrayList<Person>(people);

多くの場合、1つの複雑なクエリよりも2つの単純なクエリを実行する方が適切です。

編集:

例を挙げると、副選択ソリューションから得られたMySQLクエリのEXPLAIN出力は次のとおりです。

mysql> explain 
  select p.* from PERSON p 
    where p.id in (select p1.id from PERSON p1 where p1.name = "Joe") 
      or p.id in (select p2.id from PERSON p2 
        join CHILDREN c on p2.id = c.parent where c.name="Joe") \G
*************************** 1. row ***************************
           id: 1
  select_type: PRIMARY
        table: a
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 247554
        Extra: Using where
*************************** 2. row ***************************
           id: 3
  select_type: DEPENDENT SUBQUERY
        table: NULL
         type: NULL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: NULL
        Extra: Impossible WHERE noticed after reading const tables
*************************** 3. row ***************************
           id: 2
  select_type: DEPENDENT SUBQUERY
        table: a1
         type: unique_subquery
possible_keys: PRIMARY,name,sortname
          key: PRIMARY
      key_len: 4
          ref: func
         rows: 1
        Extra: Using where
3 rows in set (0.00 sec)

最も重要なことは、1。行はインデックスを使用せず、200k以上の行を考慮します。悪い!このクエリの実行には0.7秒かかりましたが、両方のサブクエリはミリ秒単位です。

于 2010-10-15T07:59:14.507 に答える
33

ビューを使用します。エンティティ名を使用して同じクラスを異なるテーブル/ビューにマップできるため、重複がほとんどありません。そこにいて、それをしたら、問題なく動作します。

Plain JDBC にはもう 1 つの隠れた問題があります。Hibernate セッション キャッシュを認識しないため、何かがトランザクションの最後までキャッシュされ、Hibernate セッションからフラッシュされない場合、JDBC クエリはそれを見つけられません。時々非常に困惑するかもしれません。

于 2008-10-15T00:37:08.063 に答える
7

私はウラジミールに同意しなければなりません。私もHQLでUNIONを使用することを検討しましたが、それを回避する方法が見つかりませんでした。奇妙なことは、(Hibernate FAQ で) UNION がサポートされていないこと、UNION に関するバグ報告が「修正済み」とマークされていること、UNION でステートメントが切り捨てられると言っている人々のニュースグループ、およびそれが機能していると報告している人々の他のニュースグループを見つけることができたことです。結構です...いじくり回した後、HQLをプレーンSQLに移植することになりましたが、データベースのビューでそれを行うのは良い選択肢です。私の場合、クエリの一部が動的に生成されたため、代わりにコードで SQL を作成する必要がありました。

于 2008-10-15T20:30:52.863 に答える
3

ビューはより良いアプローチですが、hql は通常 List または Set を返すため、list_1.addAll(list_2) を実行できます。組合と比べるとまったくひどいですが、うまくいくはずです。

于 2008-10-16T18:44:32.593 に答える
2

おそらく、解決すべきもっと単純な問題があったのでしょう。私の「たとえば」は、JPAプロバイダーとしてHibernateを使用したJPAにありました。

3 つの選択 (2 番目のケースでは 2 つ) を複数の選択に分割し、返されたコレクションを結合して、「すべての結合」を効果的に置き換えました。

于 2010-03-09T18:40:29.903 に答える
0

私もこの苦痛を経験してきました-クエリが動的に生成される場合(Hibernate Criteriaなど)、それを行うための実用的な方法を見つけることができませんでした。

私にとっての朗報は、Oracleデータベースで「または」を使用する場合のパフォーマンスの問題を解決するためにユニオンを調査しているだけだったことです。

パトリックが投稿した解決策(セットを使用してプログラムで結果を組み合わせる)は、醜い(特に結果のページングもやりたかったので)私には十分でした。

于 2009-01-23T01:44:18.453 に答える
0



パトリックが言ったように、各SELECTからLISTを追加することは良い考えですが、UNION ALLのように機能することを覚えておいてください。この副作用を回避するには、オブジェクトが最終コレクションに既に追加されているかどうかを制御します。いいえの場合は、追加します。 他に注意すべきことは、各SELECTにJOINがある場合、結果はオブジェクト array( ) のリストになるため、必要なオブジェクトのみを保持するためにそれを反復処理する必要があることです。 それがうまくいくことを願っています。
List<Object[]>

于 2015-11-18T10:43:13.990 に答える