문제

그만큼 원산가에 대한 구현-hibernate-getting-total-number of-row 구현 질문에 대한 질문은 또 다른 질문을 유발합니다 일부 구현 문제:

이제 카운트를 수행하기 위해 HQL 쿼리의 일부를 재사용해야한다는 것을 알고 있습니다. 효율적으로 재사용하는 방법은 무엇입니까?

두 HQL 쿼리의 차이점은 다음과 같습니다.

  1. 선택은입니다 count(?), pojo 또는 재산 (또는 목록) 대신
  2. 페치가 발생하지 않아야하므로 일부 테이블을 결합해서는 안됩니다.
  3. 그만큼 order by 사라져야합니다

다른 차이점이 있습니까?

당신은 가지고 있습니까? 이 재사용을 효율적으로 달성하기위한 최고의 실습을 코딩합니다 (관심사 : 노력, 선명도, 성과)?

간단한 HQL 쿼리의 예 :

    select       a     from A a join fetch a.b b where a.id=66 order by a.name
    select count(a.id) from A a                  where a.id=66

업데이트되었습니다

다음에 대한 답변을 받았습니다.

  • 사용 기준 (하지만 우리는 대부분 HQL을 사용합니다)
  • 문자열 조작 Query (그러나 모두가 복잡하고 안전하지 않은 것처럼 보인다는 데 동의합니다)
  • 쿼리를 포장합니다, 데이터베이스 최적화에 의존하지만 (안전하지 않다는 느낌이 있습니다)

나는 누군가가 다른 길을 따라 옵션을 제공하기를 바랐다.
공통 부품을 사용하여 두 HQL 쿼리를 모두 빌드 할 수 있습니까??

도움이 되었습니까?

해결책

좋은 질문. 내가 과거에 한 일은 다음과 같습니다 (이미 언급 한 많은 것들) :

  1. 있는지 확인하십시오 고르다 조항이 있습니다.
    1. 그렇지 않은 경우 추가하십시오 select count(*)
    2. 그렇지 않으면 그것이 있는지 확인하십시오 별개의 또는 집계 기능. Antlr을 사용하여 쿼리를 구문 분석하는 경우 이러한 작업을 수행 할 수는 있지만 상당히 관련이 있습니다. 당신은 모든 것을 select count(*) from ().
  2. 제거하다 fetch all properties
  3. 제거하다 fetch HQL을 문자열로 구문 분석하는 경우 조인에서. antlr로 쿼리를 진정으로 구문 분석하는 경우 제거 할 수 있습니다. left join 전적으로; 가능한 모든 참조를 확인하는 것은 오히려 지저분합니다.
  4. 제거하다 order by
  5. 1.2에서 수행 한 작업에 따라 제거 / 조정해야합니다. group by / having.

위는 자연스럽게 HQL에 적용됩니다. 기준 쿼리의 경우 쉽게 조작에 적합하지 않기 때문에 할 수있는 작업이 상당히 제한됩니다. 기준 위에 일종의 래퍼 레이어를 사용하는 경우 antlr 구문 분석 결과의 (제한된) 하위 집합으로 끝나고이 경우 위의 대부분을 적용 할 수 있습니다.

일반적으로 현재 페이지와 총 카운트의 오프셋을 유지하기 때문에 보통 주어진 한계 / 오프셋으로 실제 쿼리를 실행하고 count(*) 쿼리 결과 반환 수가 더 또는 동일하다면 제한이 있고 오프셋이 0입니다 (다른 모든 경우에 실행 중입니다. count(*) 전에 또는 어쨌든 모든 결과를 다시 얻었습니다). 이것은 물론 동시 수정과 관련하여 낙관적 인 접근법입니다.

업데이트 (손으로 조립 HQL)

나는 그 접근법을 특히 좋아하지 않습니다. 이름이 지정된 쿼리로 매핑되면 HQL은 빌드 타임 오류 검사의 장점이 있습니다 (일반적으로 통합 테스트 중에 수행되지만 SessionFactory가 구축되어야하므로 기술적으로 런타임이 필요합니다). 런타임에 생성되면 런타임에 실패합니다 :-) 성능 최적화를 수행하는 것도 쉽지 않습니다.

물론 동일한 추론은 기준에 적용되지만 문자열 연결과는 반대로 잘 정의 된 API로 인해 망쳐지기가 약간 어렵습니다. 병렬로 두 개의 HQL 쿼리를 구축하면 (PAGED ONE 및 "GLOBAL COUNT"ONE)도 코드 복제 (및 잠재적으로 더 많은 버그)로 이어지거나 맨 위에 어떤 종류의 래퍼 레이어를 작성하여이를 수행해야합니다. 두 가지 방법 모두 이상적이지 않습니다. 클라이언트 코드 (API 이상) 에서이 작업을 수행 해야하는 경우 문제가 더욱 악화됩니다.

나는 실제로 꽤 숙고했다 이 문제에 대한. API를 검색하십시오 최대 절전 모드-게 니체 -Dao 합리적인 타협처럼 보입니다. 위의 연결된 질문에 대한 내 답변에 자세한 내용이 있습니다.

다른 팁

(SQL?) 기준에 대한 투영을 설정하여 최대 절전 모드를 명확하게하려고 했습니까? 나는 주로 기준을 사용하고 있었기 때문에 이것이 당신의 경우에 얼마나 적용되는지 잘 모르겠지만 사용하고 있습니다.

getSession().createCriteria(persistentClass).
setProjection(Projections.rowCount()).uniqueResult()

그리고 최대 절전 모드가 캐싱 / 재사용 / 스마트 물건 자체를 알아 내게합니다. 실제로 얼마나 똑똑한 일이 실제로 얼마나 많은 일을하는지 확실하지 않습니다. 누구든지 이것에 대해 댓글을 달고 있습니까?

글쎄, 나는 이것이 모범 사례인지 확실하지 않지만 나의 실습이다 :)

쿼리가있는 경우 다음과 같은 것입니다.

select A.f1,A.f2,A.f3 from A, B where A.f2=B.f2 order by A.f1, B.f3

그리고 나는 얼마나 많은 결과를 얻을 것인지 알고 싶습니다.

select count(*) from ( select A.f1, ... order by A.f1, B.f3 )

그런 다음 결과를 Pojo를 매핑하지 않고 정수로 얻습니다.

쿼리를 구문 분석하려면 'Order By'와 같은 일부 부품을 제거하는 것은 매우 복잡합니다. 좋은 RDBMS는 귀하를 위해 귀하의 쿼리를 최적화합니다.

좋은 질문.

프리 핸드 HQL 상황에서 나는 이와 같은 것을 사용할 것이지만 이것은 주어진 엔티티에 대해 매우 구체적이므로 재사용 할 수 없습니다.

Integer count = (Integer) session.createQuery("select count(*) from ....").uniqueResult();

이 작업을 한 번 수행하고 페이지를 통과 할 때까지 시작 번호를 조정하십시오.

기준의 경우 이와 같은 샘플을 사용합니다

final Criteria criteria = session.createCriteria(clazz);  
            List<Criterion> restrictions = factory.assemble(command.getFilter());
            for (Criterion restriction : restrictions)
                criteria.add(restriction);
            criteria.add(Restrictions.conjunction());
            if(this.projections != null)
                criteria.setProjection(factory.loadProjections(this.projections));
            criteria.addOrder(command.getDir().equals("ASC")?Order.asc(command.getSort()):Order.desc(command.getSort()));
            ScrollableResults scrollable = criteria.scroll(ScrollMode.SCROLL_INSENSITIVE);
            if(scrollable.last()){//returns true if there is a resultset
                genericDTO.setTotalCount(scrollable.getRowNumber() + 1);
                criteria.setFirstResult(command.getStart())
                        .setMaxResults(command.getLimit());
                genericDTO.setLineItems(Collections.unmodifiableList(criteria.list()));
            }
            scrollable.close();
            return genericDTO;

그러나 이것은 전화를 통해 매번 계산합니다 ScrollableResults:last().

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top