2012-10-07 2 views
0

JPA에서 다음 SQL 쿼리를 작성하려고했습니다. (여전히 Java 및 JPA에 익숙하지 않으며 매우 조금 검색했지만 여전히 미안합니다. 그것은 멍청한 질문입니다). 내가 원하는 거의 수행하고JPQL Criteria Query Play Framework 1x 내부 조인 및 Where 구문 작성

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

문장을 작동하고 말씀

JPQL 쿼리는 SentenceWord가 ManyToMany이 문장과 말씀 사이에 조인 두 클래스입니다. 그래서 s.words는 문장에 속하는 목록입니다. s.Date는 가져 오기 데이터를 저장하는 가져 오기 개체입니다. : 날짜는 일치시킬 단일 가져 오기입니다. : words는 문장에서 확인하려는 단어 목록입니다.

이 쿼리는 IN 연산자에서 올바르게 작동합니다.

그러나 우리는 이제 우리가 전달하는 목록의 모든 단어가 문장에 포함되어 있는지 확인해야합니다 (s.words 목록에서 작성).

지금 당장 나는 문자열 작성기와 FOR EACH 루프를 사용하여 WHERE 절과 WHERE 절을 작성하고이를 String과 Query에 추가합니다. 그것은 작동하지만 super ugly하고 겉으로는 anti-Javay이고 올바른/typesafe 방법을하고 싶습니다.

CriteriaBuilder 및 CriteriaQuery를 찾았지만 INNER JOIN을 사용할 수 없었습니다. 조금도. 그리고 슬프게도, 그것은 RTFM 이후입니다. http://docs.jboss.org/hibernate/orm/4.0/hem/en-US/html/querycriteria.html#querycriteria-from-join

동적 들어

이것은 지금까지 내가

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

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

    ) 
); 

왔하지만 그건 그냥 모든 잘못된 것 그리고 내가 가입 할 수 없기 때문에 나는 그것을 테스트 할 수 있습니다 쿼리합니다. 누군가가 올바른 방향으로 나를 가리켜 간단한 사람들을위한 조인에 대한 CriteriaQuery 자습서를 가리키고 컬렉션을 통해 AND 절을 반복하거나이 예제에서 올바른 쿼리를 작성하면 매우 감사 할 것입니다.

UPDATE - 쿼리 효율성

대체 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 

그룹으로는 SQL에서 같은 쿼리에 대한 JQPL가 아니라 필요한 것으로 보인다. 지금은 작은 데이터 세트 만 가지고 있으므로 두 데이터 모두 매우 빠르지 만 다른 데이터를 선호하는 경우 궁금합니다.

또한 매개 변수를 설정하기 위해 쿼리를 사용하고 있는데 더 나은 클래스가 있습니까? 나는 명명 된 용어를 더 좋아한다?.

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

답변

0

다음 쿼리는 원하는대로 수행해야합니다. 더 나은 대안이 있다면 없음 아이디어 : numberOfWords 일치하는 단어의 집합에 포함 된 단어의 수입니다

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)) 

. 물론이 컬렉션에는 복제물이 없어야합니다.

쿼리가 수행하는 작업을 설명합니다. 일치시킬 단어 집합의 단어 수가이 집합의 단어 부분 수와 같고 문장에서 참조하는지 확인합니다.

+0

나는 아직 자바로 테스트하지 않았지만, 곧 할 것이지만,이 SQL은 원하는 결과를 얻는다. 하위 쿼리를 사용하는이 쿼리가 'GROUP BY s'및 'HAVING count() = : numberOfWord'를 사용하는 것보다 효과적인지 알고 계신가요? – bladmiral

+0

'group by '을 사용하는 방법이 표시되지 않습니다. –

+0

group by를 (를) 사용하여 쿼리에 대한 원래 질문의 업데이트 섹션을 참조하십시오. 쿼리와 동일한 쿼리 결과가 동일한 SQL 결과를 생성합니다. JPQL은 그런 것을 허용하지 않습니까? – bladmiral

0

당신은 dinamically과 동등한

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()); 

하여 쿼리를 작성하는 플레이 JpqlSelect를 사용할 수 있지만이 쿼리는 문장의 모든 단어를 사용하고 싶은 생각하지 동일하지 않습니다 단어 매개 변수의 각 단어. 나는 JB의 쿼리가 더 좋다라고 생각한다.

+0

나는 동적 인 쿼리를 만들기 위해 Play 프레임 워크에서 JpqlSelect 도우미 메서드에 대해 몰랐기 때문에 JBoss가이 특정 문제에 더 좋다고 생각하지만 답변에 너무 감사드립니다! 그 방법은 매우 유용 해 보입니다. 앞으로 많은 장소에서이 방법을 사용할 것입니다. – bladmiral