HQL에서 고유 한 쿼리를 생성하는 방법


100

HQL에서 고유 한 쿼리를 만드는 방법이 있습니까? "distinct"키워드 또는 다른 방법을 사용합니다. distinct가 HQL에 대해 유효한 키 워크인지 확실하지 않지만 SQL 키워드 "distinct"에 해당하는 HQL을 찾고 있습니다.

답변:


124

다음은 우리가 사용하는 hql의 일부입니다. (신분 보호를 위해 이름이 변경되었습니다.)

String queryString = "select distinct f from Foo f inner join foo.bars as b" +
                " where f.creationDate >= ? and f.creationDate < ? and b.bar = ?";
        return getHibernateTemplate().find(queryString, new Object[] {startDate, endDate, bar});

나는 MySQL에서만 최대 절전 모드를 사용했습니다-mssql 문제를 처리하는 방법을 모르겠습니다.
피트

56

distinctHQL의 distinct키워드가 SQL 의 키워드에 직접 매핑되지 않는다는 점은 주목할 가치가 있습니다.

distinctHQL 에서 키워드 를 사용하면 Hibernate는 distinctSQL 키워드를 사용하지만 어떤 상황에서는 결과 변환기를 사용하여 별개의 결과를 생성합니다. 예를 들어 다음과 같은 외부 조인을 사용하는 경우 :

select distinct o from Order o left join fetch o.lineItems

이 경우 SQL 수준에서 중복을 필터링하는 것은 불가능하므로 Hibernate는 SQL 쿼리가 수행 ResultTransformer 중복을 필터링하기 위해 a 를 사용합니다 .



16

다음에 이렇게 해주세요

 Criteria crit = (Criteria) session.
                  createCriteria(SomeClass.class).
                  setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

 List claz = crit.list();

그것은 차선책입니다. 데이터베이스 수준에서 반복을 버리는 대신 반복과 모두를 사용하여 데이터베이스에서 메모리로 데이터를 가져온 다음 나중에 반복을 삭제합니다. 데이터가 반복되는 빈도에 따라 I / O 작업이 상당히 증가 할 수 있습니다.
Haroldo_OK

9

Criteria.DISTINCT_ROOT_ENTITYHibernate HQL 쿼리와 함께 사용할 수도 있습니다 .

예:

Query query = getSession().createQuery("from java_pojo_name");
query.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
return query.list();

1
그것은 차선책입니다. 데이터베이스 수준에서 반복을 버리는 대신 반복과 모두를 사용하여 데이터베이스에서 메모리로 데이터를 가져온 다음 나중에 반복을 삭제합니다. 데이터가 반복되는 빈도에 따라 I / O 작업이 상당히 증가 할 수 있습니다.
Haroldo_OK

4

HQL 쿼리와 결합 된 결과 변환기에 몇 가지 문제가있었습니다. 내가 시도했을 때

final ResultTransformer trans = new DistinctRootEntityResultTransformer();
qry.setResultTransformer(trans);

작동하지 않았습니다. 다음과 같이 수동으로 변환해야했습니다.

final List found = trans.transformList(qry.list());

Criteria API 변환기는 잘 작동했습니다.


10k에 도달하기 위해 (:
timmz

3

내 주요 쿼리는 모델에서 다음과 같이 보입니다.

@NamedQuery(name = "getAllCentralFinancialAgencyAccountCd", 
    query = "select distinct i from CentralFinancialAgencyAccountCd i")

그리고 나는 여전히 "명확한"결과를 얻지 못했습니다. 테이블의 기본 키 조합에 따라 구별되었습니다.

그래서 DaoImpl나는 한 줄 변경을 추가하고 내가 원하는 "명확한"반환을 얻었습니다. 예를 들어 00을 네 번 보는 대신 한 번만 보는 것입니다. 다음에 추가 한 코드는 다음과 같습니다 DaoImpl.

@SuppressWarnings("unchecked")
public List<CacheModelBase> getAllCodes() {

    Session session = (Session) entityManager.getDelegate();
    org.hibernate.Query q = session.getNamedQuery("getAllCentralFinancialAgencyAccountCd");
    q.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); // This is the one line I had to add to make it do a more distinct query.
    List<CacheModelBase> codes;
    codes = q.list();
    return codes;       
}

도움이 되었기를 바랍니다. 다시 한번 말하지만, 이것은 프로젝트의 서비스, dao 및 모델 유형을 구현하는 코딩 관행을 따르는 경우에만 작동 할 수 있습니다.


2

CUSTOMER_INFORMATION 테이블에 매핑 된 고객 엔터티가 있고 고유 한 고객 이름의 목록을 가져 오려고한다고 가정합니다. 아래 스 니펫을 사용하여 동일하게 얻을 수 있습니다.

Query distinctFirstName = session.createQuery("select ci.firstName from Customer ci group by ci.firstName");
Object [] firstNamesRows = distinctFirstName.list();

도움이되기를 바랍니다. 그래서 여기서는 별개의 키워드를 사용하는 대신 그룹 별을 사용합니다.

또한 이전에는 여러 열에 적용 할 때 고유 한 키워드를 사용하는 것이 어려웠습니다. 예를 들어, 나는 구별되는 firstName, lastName의 목록을 얻고 싶습니다. 이 경우에는 distinct를 사용하는 데 어려움이있었습니다.


1

Hibernate Query Language가 Distinct 필드를 사용하는 데 대한 답을 얻었습니다. * SELECT DISTINCT (TO_CITY) FROM FLIGHT_ROUTE *를 사용할 수 있습니다. SQL 쿼리 를 사용하면 String List를 반환합니다. 엔티티 클래스별로 반환 값을 사용할 수 없습니다. 따라서 이러한 유형의 문제를 해결하는 답은 SQL 과 함께 HQL 을 사용하는 것 입니다.

FROM FLIGHT_ROUTE F WHERE F.ROUTE_ID IN (SELECT SF.ROUTE_ID FROM FLIGHT_ROUTE SF GROUP BY SF.TO_CITY);

에서 SQL의 쿼리 문은 목록으로 DISTINCT ROUTE_ID 입력을 얻었다. 그리고 IN 쿼리는 IN (목록)과 구별되는 TO_CITY를 필터링합니다.

반환 유형은 Entity Bean 유형입니다. 따라서 AutoComplement 와 같은 AJAX에서 할 수 있습니다 .

모두 괜찮을 수 있습니다


1

이와 같이 기준 작성기에서 고유 한 키워드를 사용할 수 있습니다.

CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Orders> query = builder.createQuery(Orders.class);
Root<Orders> root = query.from(Orders.class);
query.distinct(true).multiselect(root.get("cust_email").as(String.class));

그리고 모델 클래스에 필드 생성자를 만듭니다.


0

select 문에서 사용자 지정 DTO에 대해 키워드 를 사용해야 하고 고유 한 요소 가 필요한 경우 다음과 같이 new outside of new를 사용합니다.

select distinct new com.org.AssetDTO(a.id, a.address, a.status) from Asset as a where ...

0

Distinct 대신 GROUP BY를 추가 할 수 있습니다.

@Query(value = "from someTableEntity where entityCode in :entityCode" +
            " group by entityCode, entityName, entityType")
List<someTableEntity > findNameByCode(@Param("entityCode") List<String> entityCode);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.