JPA 및 최대 절전 모드-기준 대 JPQL 또는 HQL


295

Criteria 또는 HQL 사용의 장단점은 무엇입니까 ? Criteria API는 Hibernate에서 쿼리를 표현하는 훌륭한 객체 지향 방법이지만, 때로는 Criteria Queries가 HQL보다 이해 / 빌드하기가 더 어렵습니다.

언제 기준을 사용하고 언제 HQL을 사용합니까? 어떤 사용 사례에서 무엇을 선호합니까? 아니면 맛의 문제일까요?


정답은 '사용 사례에 따라 다름'입니다.
Hace

그리고 무엇에 대한 이 도구 ? 다음과 같은 방법으로 일반적인 쿼리를 생성 할 수 있습니다. protected Clause select () {return em.select ( "DISTINCT i") .from (this.getName (), "i") .joinFetch ( "i.locale lf") } 공개 T findBySlug (String slug) {return (T) this.select () .join ( "i.locale l"); .where ( "l.slug =?", slug) .fetchSingle (); }
Vojtěch

1
의견에 근거한 질문의 정의, 그러나 사람들은 질문을 닫을 기회를 가지지 않았습니다 ... 사이트 당 FAQ

답변:


212

나는 주로 동적 쿼리에 대한 기준 쿼리를 선호합니다. 예를 들어, 일부 매개 변수에 따라 일부 순서를 동적으로 추가하거나 일부 부품 (예 : 제한 사항)을 제외하는 것이 훨씬 쉽습니다.

반면에 HQL을 이해하고 읽기가 훨씬 쉽기 때문에 정적 쿼리와 복잡한 쿼리에 HQL을 사용하고 있습니다. 또한 HQL은 조금 더 강력합니다. 예를 들어 다른 조인 유형에 적합합니다.


13
또한 Criteria는 형식이 조금 더 안전 해 보이지만 안전하다고 느낄 수있는 유일한 것은 테스트입니다.

특정 경우에 HQL이 기준 api보다 나은 이유를 보여주는 좋은 예가 있습니까? 한 블로그의 끝을 읽었지만 아무 것도 이해하지 못했습니다. 도움을 주시면 감사하겠습니다. 감사. 링크 -javalobby.org/articles/hibernatequery102
Erran Morad

위의 모든 이유-프로그래머에게 더 안전하고 코딩 오류가 줄어들 기 때문에 HQL에 대한 기준을 선호합니다. HQL 문자열에 대한 컴파일은 검증되지 않습니다.
nuno

그러나 페이지 매김을하는 동안 별개의 개체를 검색하는 문제가 있습니다. 이 작업을 수행 할 때 문제를 피하기 위해 HQL을 선택했습니다.
Anthony Webster

열 이름에 메타 모델과 함께 조건 쿼리를 사용하면 리팩토링 중에 최신 IDE의 간단한 명령을 사용하여 코드에서 모든 항목의 이름을 바꾸는 데 도움이됩니다.
Massimo

92

HQL과 criteriaQuery간에 성능면에서 차이가 있습니다. criteriaQuery를 사용하여 쿼리를 실행할 때마다 테이블 이름에 대한 새 별칭이 생성되어 DB의 마지막 쿼리 캐시에 반영되지 않습니다. 이로 인해 생성 된 SQL을 컴파일하는 데 오버 헤드가 발생하여 실행 시간이 더 걸립니다.

가져 오기 전략에 관하여 [http://www.hibernate.org/315.html]

  • 기준은 매핑의 게으름 설정을 존중하며로드하려는 항목이로드되도록 보장합니다. 이는 하나의 기준 쿼리로 인해 지연되지 않은 모든 맵핑 된 연관 및 콜렉션이있는 서브 그래프를 페치하기 위해 여러 개의 SQL 즉시 SELECT 문이 발생할 수 있음을 의미합니다. "how"및 "what"을 변경하려면 setFetchMode ()를 사용하여 특정 콜렉션 또는 연관에 대한 외부 조인 페치를 활성화하거나 비활성화하십시오. 기준 쿼리는 페치 전략 (join vs select vs subselect)도 완전히 존중합니다.
  • HQL은 매핑의 게으름 설정을 존중하며로드하려는 항목이로드되도록합니다. 이는 하나의 HQL 쿼리로 인해 지연되지 않은 모든 맵핑 된 연관 및 콜렉션이있는 서브 그래프를 페치하기 위해 여러 개의 SQL 즉시 SELECT 문이 발생할 수 있음을 의미합니다. "how"및 "what"을 변경하려면 LEFT JOIN FETCH를 사용하여 특정 콜렉션 또는 널 입력 가능 다 대일 또는 일대일 연관에 대해 외부 조인 페치를 사용하거나 JOIN FETCH를 사용으로 설정하십시오. 널이 불가능한 다 대일 또는 일대일 연관을위한 내부 결합 페치. HQL 쿼리는 매핑 문서에 정의 된 fetch = "join"을 존중하지 않습니다.

1
브라우징하는 사람을 가리 킵니다. 이 답변은 2008 년에 한 것입니다. 더 이상 그렇지 않을 수도 있습니다. dimovelev.blogspot.com/2015/02/…
Amalgovinus

41

기준은 객체 지향 API이며 HQL은 문자열 연결을 의미합니다. 즉, 객체 지향의 모든 이점이 적용됩니다.

  1. 다른 모든 것이 동일하다면 OO 버전은 다소 오류가 덜 발생합니다. 기존 문자열은 HQL 쿼리에 추가 될 수 있지만 유효한 Criteria 개체 만 Criteria 트리로 만들 수 있습니다. 효과적으로 Criteria 클래스가 더 제한적입니다.
  2. 자동 완성 기능을 사용하면 OO를 더 쉽게 검색 할 수 있습니다 (적어도 사용하기 더 쉽습니다). 쿼리의 어느 부분이 어디로 갔는지 기억할 필요는 없습니다. IDE가 당신을 도울 수 있습니다
  3. 또한 구문의 특정 내용 (기호가 어디로 이동하는지 등)을 기억하지 않아도됩니다. 메소드를 호출하고 객체를 생성하는 방법 만 알면됩니다.

HQL은 SQL과 매우 유사하기 때문에 (대부분의 개발자는 이미 잘 알고 있음) 이러한 "기억할 필요가 없습니다"라는 주장은 그다지 중요하지 않습니다. HQL이 더 다르다면 더 중요 할 것입니다.


12
이러한 주장은 물을 담지 않습니다 (HQL과 관련하여). 문자열 연결을 포함하지 않아도됩니다. OO 버전이 오류가 덜 발생한다는 것은 확실하지 않습니다. 오류가 발생하기 쉽지만 다른 종류입니다. 전화에 어떤 방법을 아는 노력이 HQL에 전화를 어떤 기호를 알고에서 그렇게 많이 다르지 않다 (I 심각하게, 우리가 여기 PDE를 해결하지 않는, 의미한다.)
luis.espinal

특정 경우에 HQL이 기준 api보다 나은 이유를 보여주는 좋은 예가 있습니까? 한 블로그의 끝을 읽었지만 아무 것도 이해하지 못했습니다. 도움을 주시면 감사하겠습니다. 감사. 링크 -javalobby.org/articles/hibernatequery102
Erran Morad

1
HQL 명명 된 쿼리는 배치시 컴파일되며이 시점에서 누락 된 필드 (잘못된 리 팩터에 대한)가 감지됩니다. 나는 이것이 코드보다 탄력적이고 실제로 오류가 덜 발생한다고 생각합니다.
narduk

기준의 자동 완성은 속성이 문자열이기 때문에 거의 쓸모가 없습니다.
Lluis Martinez

35

일반적으로 입력이 어떤 데이터에 사용 될지 알지 못하는 경우 기준을 사용합니다. 사용자가 1에서 50 개 항목 중 하나를 입력 할 수있는 검색 양식과 마찬가지로 검색 대상을 숨 깁니다. 사용자가 무엇을 검색하는지 확인하는 동안 기준에 더 많은 것을 추가하는 것은 매우 쉽습니다. 그 상황에서 HQL 쿼리를 넣는 것이 조금 더 번거로울 것이라고 생각합니다. HQL은 내가 원하는 것을 정확히 알면 훌륭합니다.


1
이것은 좋은 의견입니다. 우리는 현재 조인을 통해 다양한 객체를 포함하는 검색 폼을 위해 매우 큰 HQL 문자열을 만듭니다. 못 생겼어 기준이이를 정리할 수 있는지 확인합니다. 흥미로운 ...
cbmeeks

감사. 이것은 훌륭한 예입니다. 좀 더 주 시겠어요?
Erran Morad 2018 년

31

HQL은 훨씬 쉽게 읽고, Eclipse Hibernate 플러그인과 같은 도구를 사용하여 디버깅하고, 로그하기가 더 쉽습니다. 조건 쿼리는 런타임에 많은 동작이 결정되는 동적 쿼리를 작성하는 데 더 좋습니다. SQL을 모른다면 Criteria 쿼리 사용을 이해할 수 있지만 전반적으로 내가 원하는 것을 알고 있으면 HQL을 선호합니다.



21

기준 Api는 최대 절전 모드의 좋은 개념 중 하나입니다. 내 관점에 따르면 이것들은 HQLCriteria Api를 변화시킬 수있는 몇 가지 요점입니다.

  1. HQL은 데이터에 대해 선택 및 비 선택 작업을 모두 수행하지만 기준은 데이터를 선택하기위한 것이며 기준을 사용하여 비 선택 작업을 수행 할 수 없습니다.
  2. HQL은 정적 쿼리 실행에 적합하며, 기준이 동적 쿼리 실행에 적합합니다.
  3. HQL은 페이지 매김 개념을 지원하지 않지만 Criteria로 페이지 매김을 달성 할 수 있습니다.
  4. HQL보다 실행하는 데 더 많은 시간이 소요되었습니다.
  5. Criteria를 사용하면 동적 쿼리 생성으로 인해 SQL 인젝션에 안전 하지만 쿼리가 고정되거나 매개 변수화되어 HQL에서는 SQL 인젝션으로부터 안전하지 않습니다

11
포인트 몇 페이지 매김 HQL에 있습니다 : 당신은 사용할 수 있습니다 limit offset:rows hql에서 당신은 사용 하여 SQL 주입을 피할 수 있습니다setParameter
Viswanath Lekshmanan

13

두 세계를 모두 활용하기 위해 HQL의 표현력과 간결함 및 Criteria의 동적 인 특성은 Querydsl 사용을 고려 합니다.

Querydsl은 JPA / Hibernate, JDO, SQL 및 Collections를 지원합니다.

나는 Querydsl의 관리자 이므로이 대답은 편향되어 있습니다.


13

나를 위해 기준은 동적 쿼리를 이해하고 만드는 것이 매우 쉽습니다. 그러나 내가 지금까지 말하는 결함은 Select, Proxy 및 Default의 세 가지 유형의 FetchMode 만 있기 때문에 모든 one-one 등의 관계를로드한다는 것입니다.이 모든 경우에는 many-one을로드합니다 (도움이된다면 잘못 될 수 있습니다) 나에게 :))

기준의 두 번째 문제는 완전한 객체를로드한다는 것입니다. 즉, 직원의 EmpName을로드하려는 경우이 insted와 함께 나오지 않습니다. 완전한 Employee 객체가 나오고 EmpName을 얻을 수 있습니다 . 보고 . 여기서 HQL은 원하는로드 (연결 / 관계를로드하지 않았 음)로 성능을 여러 번 향상시킵니다.

Criteria의 한 가지 특징은 ur 쿼리가 고정되거나 매개 변수화되어 HQL에서와 같이 SQL 쿼리에서 안전하지 않은 동적 쿼리 생성으로 인해 SQL 주입에서 안전하다는 것입니다.

또한 ur aspx.cs 파일에 HQL을 작성하면 ur DAL과 밀접하게 연결됩니다.

전반적으로 결론은 보고서와 같이 HQL 없이는 살 수없는 곳이 있다는 것입니다. 그렇지 않으면 기준을 관리하기가 더 쉽습니다.


13
HQL은 SQL 주입 안전하지 않습니다
하기 Varun 메타

나는 기준이 주입 안전하지 않다고 생각합니다. 내 게시물보기 : stackoverflow.com/questions/6746486/…
Mister Smith

4
HQL은 'setParameter를'을 가산함으로써 SQL 인젝션 안전 인
Javatar

2
@Zafar : 투영법을 사용하여 개체의 특정 속성 만 선택할 수 있습니다
Răzvan Flavius ​​Panda

@Zafar 기준 쿼리에서 투영을 설정하여 특정 열을 선택할 수 있습니다. 완전한 객체를 가져올 필요없이 EmpName을 가져올 수 있습니다.
Khatri

12

기준 API

기준 API는 동적으로 생성 된 쿼리에 더 적합합니다. 따라서 WHERE 절 필터, JOIN 절을 추가하거나 ORDER BY 절 또는 프로젝션 열을 변경하려는 경우 Criteria API를 사용 하면 SQL 주입 공격을 방지 하는 방식으로 쿼리를 동적으로 생성 할 수 있습니다 .

반면에 기준 쿼리는 표현력 이 떨어지며이 기사 에서 설명하는 것처럼 매우 복잡하고 비효율적 인 SQL 쿼리로 이어질 수도 있습니다. .

JPQL 및 HQL

JPQL은 JPA 표준 엔터티 쿼리 언어이며 HQL은 JPQL을 확장하고 일부 Hibernate 관련 기능을 추가합니다.

JPQL과 HQL은 매우 표현력이 뛰어나며 SQL과 유사합니다. Criteria API와 달리 JPQL 및 HQL을 사용하면 JPA 제공자가 생성 한 기본 SQL 쿼리를 쉽게 예측할 수 있습니다. 또한 기준 쿼리보다 HQL 쿼리를 검토하는 것이 훨씬 쉽습니다.

JPQL 또는 Criteria API를 사용하여 엔티티를 선택하면 엔티티를 수정해야하는 경우 의미가 있습니다. 그렇지 않으면 DTO 투영 이 훨씬 더 나은 선택입니다.

결론

엔터티 쿼리 구조를 변경할 필요가 없으면 JPQL 또는 HQL을 사용하십시오. 필터링 또는 정렬 기준을 변경하거나 프로젝션을 변경해야하는 경우 Criteria API를 사용하십시오.

그러나 JPA 또는 최대 절전 모드를 사용한다고해서 기본 SQL을 사용해서는 안된다는 의미는 아닙니다. SQL 쿼리는 매우 유용하며 JPQL 및 Criteria API는 SQL을 대체하지 않습니다. 이 주제에 대한 자세한 내용은 이 기사 를 확인하십시오 .



11

나를 위해 Criteria에서 가장 큰 승리는 Example API입니다. 여기서 객체를 전달할 수 있으며 최대 절전 모드는 해당 객체 속성을 기반으로 쿼리를 작성합니다.

그 외에도 기준 API에는 다음과 같은 단점이 있습니다 (최대 절전 모드 팀이 API를 다시 작성한다고 생각합니다).

  • criteria.createAlias ​​( "obj")는 가능한 외부 조인 대신 내부 조인을 강제합니다.
  • 동일한 별칭을 두 번 만들 수 없습니다
  • 일부 SQL 절에는 간단한 기준이 없습니다 (예 : subselect)
  • 기타

sql과 비슷한 쿼리를 원할 때 HQL을 사용하는 경향이 있으며 (state = 'blocked'인 사용자에서 삭제) 문자열 추가를 사용하지 않으려는 경우 기준을 사용하는 경향이 있습니다.

HQL의 또 다른 장점은 미리 모든 쿼리를 정의하고 파일 등으로 외부화 할 수 있다는 것입니다.


9

기준 API는 SQL 또는 HQL이 제공하지 않는 고유 한 기능을 제공합니다. 즉. 쿼리의 컴파일 시간 검사를 허용합니다.


7

우리는 처음에는 응용 프로그램에서 기준을 주로 사용했지만 성능 문제로 인해 HQL로 대체 된 후에 사용했습니다.
주로 여러 조인으로 매우 복잡한 쿼리를 사용하여 Criteria에서 여러 쿼리를 생성하지만 HQL에서 매우 최적화되었습니다.
경우는 특정 객체에 대해 몇 가지 속성 만 사용하고 완전한 객체는 사용하지 않는 것입니다. 기준으로 문제는 문자열 연결이었습니다.
HQL에서 사용자의 이름과 성을 표시 해야하는 경우 매우 쉽지만 (name || ' ' || surname)Crteria에서는 불가능합니다.
이를 극복하기 위해 ResultTransormers를 사용했는데, 필요한 결과를 위해 그러한 연결이 구현 된 방법이있었습니다.
오늘날 우리는 주로 다음과 같이 HQL을 사용합니다.

String hql = "select " +
            "c.uuid as uuid," +
            "c.name as name," +
            "c.objective as objective," +
            "c.startDate as startDate," +
            "c.endDate as endDate," +
            "c.description as description," +
            "s.status as status," +
            "t.type as type " +
            "from " + Campaign.class.getName() + " c " +
            "left join c.type t " +
            "left join c.status s";

Query query =  hibernateTemplate.getSessionFactory().getCurrentSession().getSession(EntityMode.MAP).createQuery(hql);
query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
return query.list();

따라서이 경우 반환 된 레코드는 필요한 속성의 맵입니다.


1
Criteria를 사용하면 org.hibernate.criterion.CriteriaSpecification.ALIAS_TO_ENTITY_MAP
AA

내 경험에서지도 목록을 반환하면 성능이 매우 떨어집니다. 객체 배열 목록이나 빈 목록을 반환하는 것을 선호합니다 (항상 특정 결과 집합에 맞는 빈을 정의 할 수 있음).
Lluis Martinez

7
  • HQL은 데이터에 대해 선택 및 비 선택 작업을 모두 수행하지만 기준은 데이터를 선택하기위한 것이며 기준을 사용하여 비 선택 작업을 수행 할 수 없습니다.
  • HQL은 정적 쿼리 실행에 적합하며, 기준이 동적 쿼리 실행에 적합합니다.
  • HQL은 페이지 매김 개념을 지원하지 않지만 기준으로 페이지 매김을 달성 할 수 있습니다
  • HQL보다 실행하는 데 더 많은 시간이 걸리는 기준
  • Criteria를 사용하면 동적 쿼리 생성으로 인해 SQL 인젝션이 안전하지만 쿼리가 고정되거나 매개 변수화되어 HQL에서는 SQL 인젝션이 안전하지 않습니다.

출처


명확히하기 위해, Hibernate의 Criteria API를 사용하는 기준 질의가 질의에 이용 될 수 있지만, JPA 기준 질의는 선택, 업데이트 및 삭제를 포함한다. 참조 CriteriaUpdate<T>CriteriaDelete<T>참조.
Naros

5

동적에 대한 기준 쿼리는 입력을 기반으로 쿼리를 생성 할 수 있습니다. Hql 쿼리의 경우 정적 쿼리는 일단 생성 한 후에는 쿼리 구조를 변경할 수 없습니다.


2
별로. HQL을 사용하면 ':'식별자로 속성을 설정 한 다음 해당 속성을 고유 한 값으로 바꿀 수 있습니다. 예를 들어, Query q = session.createQuery ( "SELECT : aValue FROM my_table"); q.setParameter ( "aValue", "some_column_name");
MattC

@MattC이 예에서는 쿼리 구조가 아니라 매개 변수의 값을 변경하고 있습니다.
Czar

4

여기서 죽은 말을 쫓고 싶지 않지만 기준 쿼리가 더 이상 사용되지 않는다는 것을 언급하는 것이 중요합니다. HQL을 사용하십시오.


1

또한 동적 쿼리에 대한 기준 쿼리를 선호합니다. 그러나 부모 쿼리 'xyz'의 자식 테이블에서 모든 레코드를 삭제하는 경우와 같이 쿼리 삭제에 hql을 선호합니다 .HQL로 쉽게 달성 할 수 있지만 기준 API의 경우 먼저 n 개의 자식 쿼리를 실행해야합니다. 여기서 n은 자식 수입니다 테이블 기록.


0

여기에 대한 답변 대부분이 오해하고 언급하는 Criteria Queries속도가 느린보다HQL 은 실제로는 그렇지 않습니다.

심도를 조사하고 일부 테스트를 수행하면 기준 쿼리가 일반 HQL보다 훨씬 더 나은 성능을 볼 수 있습니다. 냅니다.

또한 Criteria Query 를 사용하면 HQL 에는없는 객체 지향 제어 를 얻습니다. 있습니다.

자세한 내용은 여기 에서이 답변을 읽으 십시오 .


0

다른 방법이 있습니다. 최대 절전 모드의 원래 구문을 기반으로 HQL 파서를 작성하여 먼저 HQL을 구문 분석 한 다음 동적 매개 변수를 동적으로 삽입하거나 HQL 쿼리에 대한 공통 필터를 자동으로 추가 할 수있었습니다. 잘 작동합니다!


0

이 게시물은 꽤 낡았습니다. 대부분의 답변은 JPA 기준이 아닌 최대 절전 모드 기준에 대해 설명합니다. JPA 2.1에는 정확하게 가져올 항목을 제어하는 ​​CriteriaDelete / CriteriaUpdate 및 EntityGraph가 추가되었습니다. Java가 OO이므로 기준 API가 더 좋습니다. 이것이 JPA가 만들어지는 이유입니다. JPQL을 컴파일하면 SQL로 변환하기 전에 AST 트리 (OO 모델)로 변환됩니다.


-3

HQL은 SQL 삽입과 같은 보안 문제 를 일으킬 수 있습니다 .


11
이러한 문제는 HQL이 아니라 기본 소프트웨어 개발 관행에 대한 이해 부족으로 인해 발생합니다. 조건 api를 사용하여 SQL 주입 공격에 취약한 코드를 만들 수도 있습니다.
Jens Schauder

1
"Java에서 RDBMS를 쿼리하면 SQL 주입 보안 문제가 발생할 수 있습니다"라고 말하는 것과 같습니다. : D
Czar
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.