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 对象,用于存储导入的东西数据:date 是我们要匹配的单个 Import。:words 是我们要在句子中检查的单词的列表。

此查询对 IN 运算符工作得很好。

然而,我们现在需要检查一个句子是否包含我们正在传递的列表中的所有单词(我们从 s.words 列表中组装)。

现在我只是使用字符串生成器和 FOR EACH 循环手动构建 WHERE AND 子句,并将它们附加到字符串和使用查询。它可以工作,但它超级丑陋并且看似反Javay,我想以正确/类型安全的方式来做。

我找到了 CriteriaBuilder 和 CriteriaQuery 但只是无法让 INNER JOIN 工作。完全没有。可悲的是,这是在我 RTFM 之后。http://docs.jboss.org/hibernate/orm/4.0/hem/en-US/html/querycriteria.html#querycriteria-from-join

对于动态 WHERE AND 查询,据我所知

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

JQPL 似乎需要 Group By,但对于 SQL 中的同一查询则不需要。我现在只有一个小数据集,所以两者都很快,但很好奇一个是否比另一个更受欢迎。

另外,我只是使用 Query 来设置参数,是否有更好的类用于这些?我更喜欢命名术语而不是?。

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

以下查询应该做你想做的事。不知道是否有更好的选择:

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 回答
0

您可以在游戏中使用 JpqlSelect 来动态地构建您的查询

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 回答