0

hibernate/hql を使用してクエリを作成しています。ここで状況を理解するために、私はかなりの時間立ち往生している問題を抱えています。

情報を取得する必要がある 3 つのテーブルを取得し、全体で 5 つの接続/割り当てテーブルを取得しました。必要な情報は Key、Type、および SourceFile ですが、ここでの特別なケースは、新しいデータのインポート中に SQL が実行されることです。そのため、データが既に存在するか、部分的に存在するかを最初に確認したいと考えています。キー自体が既にデータベースにある場合、Type または SourceFile に関係なく、クエリは常にキーを提供する必要があります。また、キーのみが必要であり、他の情報は必要ありません。(キーは一致しますが、SourceFile と Type は一致しないので、キーだけを返したいです) Key がまったく同じ Type と SourceFile で存在する場合、すべての情報を取得したいと考えています。

テーブルは次のとおりです。

(注意: FK_K_ID は名前キーを持つオブジェクトとして保存され、FK_S_ID はソースとして保存され、FK_T_ID はタイプとして保存されます)

鍵:

+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| K_ID        | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| key         | varchar(255) | NO   |     | NULL    |                |
| deleted     | boolean      | NO   |     | FALSE   |                |
+-------------+--------------+------+-----+---------+----------------+

キータイプ:

+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| KT_ID       | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| FK_K_ID     | bigint(20)   | NO   |     | NULL    |                |
| FK_T_ID     | bigint(20)   | NO   |     | NULL    |                |
| deleted     | boolean      | NO   |     | FALSE   |                |
+-------------+--------------+------+-----+---------+----------------+

タイプ:

+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| T_ID        | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| name        | varchar(255) | NO   |     | NULL    |                |
| description | varchar(255) | NO   |     | NULL    |                |
| deleted     | boolean      | NO   |     | FALSE   |                |
+-------------+--------------+------+-----+---------+----------------+

キーソース:

+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| KS_ID       | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| FK_K_ID     | bigint(20)   | NO   |     | NULL    |                |
| FK_S_ID     | bigint(20)   | NO   |     | NULL    |                |
| deleted     | boolean      | NO   |     | FALSE   |                |
+-------------+--------------+------+-----+---------+----------------+

ソース:

+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| S_ID        | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| sourceFile  | varchar(255) | NO   |     | NULL    |                |
| deleted     | boolean      | NO   |     | FALSE   |                |
+-------------+--------------+------+-----+---------+----------------+

これが私がこれまでに試したことです:

from KeyType kt
right outer join kt.Key k
with k.name in (...)
where k.deleted = false
and ( kt.Type in (...) or kt is null )

これの問題は、それが私が望むことをするということです。しかし、データベース内のすべてのキーと、一致する場所のみの KeyType を取得し、それ以外の場合は null を取得します。すべてのキーを取得するのではなく、要求したキーを取得したいだけです。

from KeyType kt
right outer join kt.Key k
with k.name in (...)
where k.deleted = false
and (k.name in (...) and kt.Type in (...) or kt is null )

正直に言うと、ここで何を試みたのかさえわかりません。最初のクエリを最適化して、要求したキーのみを提供しようとしたと思います。

from KeyType kt
right outer join fetch kt.Key k
where k.deleted = false
and (k.name in (...) and kt.Type in (...) or kt is null )

また、このようなまたは他のバリエーションでフェッチを使用しようとしましたが、必要なように機能しませんでした。

from Key k
left outer join KeyType kt on kt.Key.id = k.id
left outer join KeySource ks on ks.Key.id = k.id
inner join Source s on ks.Source.id = s.id
where k.deleted = false
and k.name in (...)
and ( kt.appType in (...) or kt is null )
and ( s.SourceFile in (...) or s is null )

予想通り、これは機能しません。つまり、うまくいかないことがわかるのは非常に簡単ですが、うまくいかない場合はたくさん試してみてください。

さらに多くのクエリの組み合わせとバリエーションを試しましたが、うまくいきませんでした。最初のクエリは、私が得た最も近いものです。誰かが私を助けてくれることを願っています。

PS: 今はマッピングやエンティティを変更できません。私は得たもので働かなければなりません。

アップデート:

わかりましたので、問題の解決に非常に近づいています。私のクエリは次のようになります。

select k, case when kt.Type not in (...) then null
               else 1 end
from KeyType kt
join kt.Key k
where k.name in (...)

今私がしたいのは、1を実際のオブジェクトと交換することだけです。しかし、これを行うと、「org.hibernate.exception.GenericJDBCException: could not execute query」というエラーが表示されます (Oracle データベースで実行)

誰かがそれを解決する方法を教えてもらえますか?

4

1 に答える 1

0

私の場合、私がやりたかった方法で周りを囲むことは不可能です。

そこで、もう一度同僚に尋ねたところ、単一のクエリで実行する必要がある解決策にたどり着きました。

同じテーブル構成/問題でこの投稿を通り過ぎる人のためにこれを言っているだけです。

于 2016-08-04T08:32:29.740 に答える