2009-10-21 2 views
1

최대 절전 모드에 익숙하지 않은 것에 대해 사과하고 싶습니다. 나는 최근에야 그것에 들어가서 전문가와는 거리가 멀다.ANY 대신 ALL으로 Hibernate "IN"절

나는 계약, 제품 및 다 대다 관계를 정의하는 링크 테이블을 세 가지 테이블로 가지고 있습니다.

범위의 제품을 포함하는 모든 계약을 반환하는 HQL 쿼리를 작성하려고합니다. 불행하게도 IN 구문은 All 대신 Any처럼 작동합니다. 따라서 ProductA, ProductB 및 ProductC가있는 모든 계약을 원할 경우 IN 키워드는 모든 계약이 아닌 해당 제품의 개별 계약이있는 계약을 반환합니다.

HQL 쿼리를 어떻게 구성해야합니까?

답변

3

INAND처럼 동작 할 것으로 기대합니까? 내 지식에 따라 INOR 일종의 AND이 아닙니다. IN은 당신이 찾고있는 것이 아니기 때문입니다. 콜렉션 값 경로 표현식을

  • HQL 기능 : size(), minelement(), maxelement(), minindex(), maxindex() 사용하여 정량화 할 수있는 특별한 elements()indices 기능과 함께, 특히 Hibernate의 Expressions의 모양과 되세요 일부, 모두, 어떤이에, 존재한다.

[...]

은 SQL 함수를 어떤 일부는 모두, 존재 컬렉션의 요소 또는 인덱스 세트 (elements 함수와 indices 함수) 또는 서브 쿼리의 결과를 전달했을 때 지원된다 (아래 참조)

[...]

from Show show where 'fizard' in indices(show.acts) 
+0

그래서 찾고있을 것입니다 무슨? – JustLoren

+0

위의 쿼리가 OP의 질문을 어떻게 해결할 수 있는지 설명 할 수 있습니까? indices()는 엔티티 수집 요소 AFAIK에 대한 속성 값을 반환하지 않습니다. 그리고 그렇게해도 모든 제품이 해당 컬렉션에 포함되지는 않습니다. – ChssPly76

2

당신은 group by/having 사용할 수 있습니다

select c 
    from Contract c join c.products p 
where p.name in ('A', 'B', 'C') 
group by c.id, // list ALL Contract properties 
having count(*) = 3 

은 또한 당신이 group by의 모든 속성 목록을 피하기 위해 subquery를 사용할 수 있습니다

,
from Contract c where c.id in (
select c.id 
    from Contract c join c.products p 
where p.name in ('A', 'B', 'C') 
group by c.id 
having count(*) = 3 
) 

분명히 "3"은 in 절에 입력 한 실제 제품 이름으로 대체해야합니다.

+0

A, B 또는 C 중 하나 인 3 개의 관련 제품이있는 계약을 반환하지 않겠습니까? – serg

+1

아니요, 그렇지 않습니다. 그러나 제품 A, A 및 B와 연관된 계약을 반환합니다. 그 경우 (관계가 중복을 허용하는 경우)이를 해결할 수있는 유일한 방법은 명시 적 조인 3 개가있는 중첩 된 쿼리를 생성하는 것입니다. – ChssPly76

+1

좋아, 방금 쿼리를 테스트했습니다. 귀하의 제품 중 적어도 A, B, C가있는 모든 계약이 선택되며 (따라서 ABCD 및 XYZABC가 선택됩니다), 광산은 정확히 ABC를 선택합니다. 어떤 질문이 필요한지는 명확하지 않으므로 둘 다 다른 업무에 유용합니다. – serg

0

blog 나는 최대 절전 모드 쿼리를 수행 했으므로 예제 # 4를 살펴보십시오. 절에 그렇지 않으면 유래를 극복하기 위해 기준을 사용 [from group where groupid in(select id from elemtable)]

같은 하위 쿼리를 사용에서 2000 개 이상의 ID에 대한

String[] tags = {"Java", "Hibernate"}; 
String hql = "select a from Article a " + 
       "join a.tags t " + 
       "where t.name in (:tags) " + 
       "and a.id in (" + 
        "select a2.id " + 
        "from Article a2 " + 
        "join a2.tags t2 " + 
        "group by a2 " + 
        "having count(t2)=:tag_count) " + 
       "group by a " + 
       "having count(t)=:tag_count"; 
Query query = session.createQuery(hql); 
query.setParameterList("tags", tags); 
query.setInteger("tag_count", tags.length); 
List<Article> articles = query.list(); 
+0

'group by a'는 불법입니다 : http://docs.jboss.org/hibernate/stable/core/reference/en/html/queryhql.html#queryhql-grouping – ChssPly76

+0

"group by a.id"라고 쓸 수 있습니다. 현재와 ​​똑같지 만, 현재의 것 또한 잘 동작하며, 그냥 MySQL에서 테스트했습니다. – serg

+0

MySQL은'group by' 절의 엄격한 취급으로 정확하게 알려지지 않았습니다. Postgres 나 Oracle에서 같은 트릭을 시도해보십시오 :-)'group by a.id' 역시 마찬가지로 불법입니다. 왜냐하면 SQL 표준은 집계 함수를 사용하는'select' 절에서 집계되지 않은 컬럼을'group by' 절. 귀하의 경우에는 기사 이름이 아닐 것입니다. 당신의 질문이 나쁘다고 말하는 것이 아닙니다. 모든 열을 명시 적으로 나열해야합니다. – ChssPly76

2

: 여기

스냅 샷 (제품과 함께 계약과 기사 및 태그를 교체를)입니다 오류.

예 :

Session session = getHibernateTemplate().getSessionFactory().openSession(); 

Criteria criteriaEaquals = session.createCriteria(Elements.class); 
criteriaEaquals.add(Restrictions.in("elementId", elemIds)); 
criteriaEaquals.setProjection(Projections.distinct(Projections.property("type"))); 
List list = criteriaEaquals.list(); 

session.close(); 
System.out.println("typelistis--->"+list.toString()); 

return list;