0

JPAで次のSQLクエリを作成しようとして立ち往生しています(JavaとJPAはまだ新しいので、かなり検索しましたが、まだ取得できません。初心者の質問の場合は申し訳ありません)。

私が望んでいることをほぼ実行し、機能するJPQLクエリ

SELECT s
FROM Sentence s
INNER JOIN s.words sw
WHERE s.date = :date
AND sw IN (:words)

SentenceとWordはどちらもクラスですSentenceWordは、SentenceとWordの間のManyToMany結合です。つまり、s.wordsはセンテンスに属するリストです。s.Dateは、スタッフデータを格納するImportオブジェクトです。import:dateは、照合する単一のImportです。:wordsは、文中でチェックしたい単語のリストです。

このクエリは、IN演算子に対しては問題なく機能します。

ただし、現在、センテンスに、渡すリスト内のすべての単語が含まれているかどうかを確認する必要があります(s.wordsリストからアセンブルします)。

現在、文字列ビルダーとFOREACHループを使用してWHEREAND句を手動で作成し、それらを文字列に追加してクエリを使用しています。それは動作しますが、それは非常に醜く、一見反Javayであり、私はそれを正しい/タイプセーフな方法でやりたいと思っています。

CriteriaBuilderとCriteriaQueryを見つけましたが、INNERJOINを機能させることができませんでした。まったく。そして悲しいことに、それは私がRTFMした後です。http://docs.jboss.org/hibernate/orm/4.0/hem/en-US/html/querycriteria.html#querycriteria-from-join

動的なWHEREANDクエリの場合、これは私が得た限りです

q.where(
    cb.and(
        cb.equal(s.get("date"), date)

        for (Word word : words) {
            , cd.equal(s.get("words"), word)          
        }

    )
);

しかし、それはすべて間違っているように思われ、参加できないため、テストできません。誰かが私を単純な人々の結合とコレクションをループしてAND句を作成するためのCriteriaQueryチュートリアルの正しい方向に向けることができれば、またはこの例で正しいクエリを書き出すことができれば、私は非常にありがたいです!

更新-クエリの効率

代替のJPQLクエリは次のようになります。

SELECT s 
FROM Sentence s
INNER JOIN s.words sw
WHERE s.date = :date
AND sw IN (:words)
GROUP BY s
HAVING count(sw) = :numberOfWords

Group ByはJQPLで必要とされているようですが、SQLの同じクエリでは必要ありません。私は今小さなデータセットを持っているので、両方とも非常に高速ですが、一方が他方よりも優先されるかどうか興味があります。

また、クエリを使用してパラメータを設定していますが、これらに使用するより良いクラスはありますか?名前付きの用語の方が?よりも好きです。

Query query = JPA.em().createQuery(jpql);
query.setParameter("date", date);
query.setParameter("numberOfWords", new Long(words.size()));
query.setParameter("words", words);
4

2 に答える 2

0

JpqlSelectを使用して、andとequalを使用してクエリを動的に構築できます。

JpqlSelect select = new JpqlSelect();
Map<String, Object> params = new HashMap<String, Object>();
select.select("s");
select.from("Sentence s inner join s.words sw");
select.where("where s.date = ?");
params.param(date);
for (Word word : words) {
    select.andWhere("sw = ?");
}
return fin(select.toString(), select.getParams());

しかし、このクエリは、文のすべての単語を使用したいクエリではないと思います。これは、wordsパラメータの各単語と同じではありません。JBのクエリの方がいいと思います

于 2012-10-08T05:39:13.020 に答える
0

次のクエリはあなたが望むことをするはずです。より良い代替案があるかどうかはわかりません:

select s 
from Sentence s
where s.date = :date
and :numberOfWords = (select count(sw) from SentenceWord sw
                      where sw.sentence = s
                      and sw in (:words))

ここnumberOfWordsで、は一致する単語のコレクションに含まれる単語の数です。もちろん、このコレクションには重複が含まれていてはなりません。

クエリの機能を説明するには、一致する単語のセット内の単語の数が、このセットの一部であり、文によって参照されている単語の数と等しいことを確認します。

于 2012-10-07T15:02:30.813 に答える