문제

최대 절전 모드를 사용하여 노조 쿼리를 구현 해야하는 대안은 무엇입니까? 현재 Hibernate가 현재 Union Queries를 지원하지 않는다는 것을 알고 있습니다. 지금 제가 노조를 만드는 유일한 방법은보기 테이블을 사용하는 것입니다.

다른 옵션은 일반 JDBC를 사용하는 것이지만,이 방법으로 모든 예제/기준 쿼리 케이크와 최대 절전 모드가 테이블/열에 대해 수행하는 최대 절전 모드 매핑 검증을 잃게됩니다.

도움이 되었습니까?

해결책

보기보기. 동일한 클래스를 엔티티 이름을 사용하여 다른 테이블/뷰에 매핑 할 수 있으므로 중복이 많지 않습니다. 그곳에 있다는 것은 괜찮습니다.

일반 JDBC에는 또 다른 숨겨진 문제가 있습니다. 최대 절전 모드 세션 캐시를 알지 못하므로 거래가 끝날 때까지 무언가가 캐시되고 최대 절전 모드 세션에서 플러시되지 않으면 JDBC 쿼리가 찾을 수 없습니다. 때때로 매우 수수께끼 일 수 있습니다.

다른 팁

당신은 사용할 수 있습니다 id in (select id from ...) or id in (select id from ...)

예를 들어 대신 비 작동

from Person p where p.name="Joe"
union
from Person p join p.children c where c.name="Joe"

당신은 할 수 있습니다

from Person p 
  where p.id in (select p1.id from Person p1 where p1.name="Joe") 
    or p.id in (select p2.id from Person p2 join p2.children c where c.name="Joe");

적어도 MySQL을 사용하면 나중에 성능 문제가 발생합니다. 대신 두 쿼리에서 가난한 사람의 가입을하기가 더 쉽습니다.

// use set for uniqueness
Set<Person> people = new HashSet<Person>((List<Person>) query1.list());
people.addAll((List<Person>) query2.list());
return new ArrayList<Person>(people);

하나의 복잡한 쿼리보다 두 개의 간단한 쿼리를하는 것이 종종 더 좋습니다.

편집하다:

예를 들어, 다음은 SubSelect 솔루션에서 결과 MySQL 쿼리의 설명 출력입니다.

mysql> explain 
  select p.* from PERSON p 
    where p.id in (select p1.id from PERSON p1 where p1.name = "Joe") 
      or p.id in (select p2.id from PERSON p2 
        join CHILDREN c on p2.id = c.parent where c.name="Joe") \G
*************************** 1. row ***************************
           id: 1
  select_type: PRIMARY
        table: a
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 247554
        Extra: Using where
*************************** 2. row ***************************
           id: 3
  select_type: DEPENDENT SUBQUERY
        table: NULL
         type: NULL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: NULL
        Extra: Impossible WHERE noticed after reading const tables
*************************** 3. row ***************************
           id: 2
  select_type: DEPENDENT SUBQUERY
        table: a1
         type: unique_subquery
possible_keys: PRIMARY,name,sortname
          key: PRIMARY
      key_len: 4
          ref: func
         rows: 1
        Extra: Using where
3 rows in set (0.00 sec)

가장 중요한 것은 1. 행은 인덱스를 사용하지 않으며 200k+ 행을 고려합니다. 나쁜! 이 쿼리의 실행은 0.7 초가 걸렸습니다.

블라디미르에 동의해야합니다. 나도 HQL에서 Union을 사용하는 것을 살펴 보았고 그 주위에 길을 찾을 수 없었습니다. 이상한 점은 (최대 절전 모드 FAQ에서) Union이 지원되지 않는다는 것을 찾을 수 있다는 것이었고, '고정 된'노조와 관련된 버그 보고서, 노조에서 진술이 잘릴 것이라고 말하는 사람들의 뉴스 그룹 및 기타 뉴스 그룹이 그것을보고하는 사람들의 뉴스 그룹이 발견되었습니다. 괜찮아 ... 하루 종일 멍청한 후, 나는 HQL을 일반 SQL로 다시 포팅했지만 데이터베이스에서보기에서 그것을하는 것은 좋은 선택 일 것입니다. 제 경우에는 쿼리의 일부가 동적으로 생성되었으므로 대신 코드에서 SQL을 빌드해야했습니다.

HQL에서 Union과 함께 한 가지 중요한 시나리오 (많은 어려움을 겪고 있음)에 대한 솔루션이 있습니다.

예 : 작동하지 않는 대신 :-

select i , j from A a  , (select i , j from B union select i , j from C) d where a.i = d.i 

또는

select i , j from A a  JOIN (select i , j from B union select i , j from C) d on a.i = d.i 

Hibernate HQL->에서 할 수 있습니다

Query q1 =session.createQuery(select i , j from A a JOIN B b on a.i = b.i)
List l1 = q1.list();

Query q2 = session.createQuery(select i , j from A a JOIN C b on a.i = b.i)
List l2 = q2.list();

그런 다음 두 목록을 모두 추가 할 수 있습니다 ->

l1.addAll(l2);

보기는 더 나은 접근 방식이지만 HQL은 일반적으로 목록을 반환하거나 설정합니다 ... List_1.addall (list_2)을 수행 할 수 있습니다. 노동 조합에 비해 완전히 짜증나지만 효과가 있어야합니다.

아마도 나는 해결해야 할 더 간단한 문제가 있었을 것입니다. 예를 들어 'Fore'는 JPA에 JPA 제공 업체로서 JPA에있었습니다.

세 개의 선택 (두 번째 경우 2 개)을 여러 선택으로 나누고 컬렉션을 결합하여 'Union All'을 효과적으로 대체했습니다.

저도이 고통을 겪었습니다. 쿼리가 동적으로 생성되면 (예 : 최대 절전 모드 기준) 실용적인 방법을 찾을 수 없었습니다.

나에게 좋은 소식은 Oracle 데이터베이스에서 '또는'를 사용할 때 성능 문제를 해결하기 위해 Union을 조사하고 있다는 것입니다.

Patrick이 게시 한 솔루션 (세트를 사용하여 프로그래밍 방식으로 결과를 결합)은 추악한 반면 (특히 결과 페이징도 원했기 때문에)는 나에게 적합했습니다.



패트릭이 말했듯이 목록각각에서 s 고르다 좋은 생각이지만 그것은 모두. 이 부작용을 피하려면 최종 컬렉션에 객체가 이미 추가되었는지 여부를 제어하십시오. 아니오라면 추가하십시오.
당신이 관심을 가져야 할 다른 것은 가입하다고르다, 결과는 객체 배열 목록입니다 (List<Objetc[]>) 따라서 필요한 물체 만 유지하려면 반복해야합니다.

그것이 효과가 있기를 바랍니다.

특별한 경우가 있지만, 자신의 작업을 만들도록 영감을 줄 수 있습니다. 여기서 목표는 레코드가 특정 기준을 충족하는 두 개의 다른 테이블에서 총 레코드 수를 계산하는 것입니다. 이 기술은 여러 테이블/소스에서 데이터를 집계 해야하는 모든 경우에 효과가 있다고 생각합니다.

특별한 중간 클래스 설정이 있으므로 이름이 지정된 쿼리를 호출하는 코드는 짧고 달콤하지만 쿼리를 실행하기 위해 이름이 지정된 쿼리와 함께 일반적으로 사용하는 모든 메소드를 사용할 수 있습니다.

QueryParms parms=new QueryParms();
parms.put("PROCDATE",PROCDATE);

Long pixelAll = ((SourceCount)Fetch.row("PIXEL_ALL",parms,logger)).getCOUNT();

여기에서 볼 수 있듯이 이름이 지정된 쿼리는 노조 진술과 같이 놀랍습니다.

@Entity
@NamedQueries({
        @NamedQuery(
            name  ="PIXEL_ALL",
            query = "" +
                    "  SELECT new SourceCount(" +
                    "     (select count(a) from PIXEL_LOG_CURR1 a " +
                    "       where to_char(a.TIMESTAMP, 'YYYYMMDD') = :PROCDATE " +
                    "     )," +
                    "     (select count(b) from PIXEL_LOG_CURR2 b" +
                    "       where to_char(b.TIMESTAMP, 'YYYYMMDD') = :PROCDATE " +
                    "     )" +
                    ") from Dual1" +
                    ""
    )
})

public class SourceCount {
    @Id
    private Long   COUNT;

    public SourceCount(Long COUNT1, Long COUNT2) {
        this.COUNT = COUNT1+COUNT2;
    }

    public Long getCOUNT() {
        return COUNT;
    }

    public void setCOUNT(Long COUNT) {
        this.COUNT = COUNT;
    }
}

여기 마법의 일부는 더미 테이블을 만들고 하나의 레코드를 삽입하는 것입니다. 내 경우에는 데이터베이스가 Oracle이기 때문에 Dual1이라고 불렀지 만 더미 테이블이라고 부르는 것이 중요하지 않다고 생각합니다.

@Entity
@Table(name="DUAL1")
public class Dual1 {
    @Id
    Long ID;
}

더미 레코드를 삽입하는 것을 잊지 마십시오 :

SQL> insert into dual1 values (1);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top