1. 엔티티 객체 쿼리
엔티티 객체 쿼리는 HQL 쿼리의 기초입니다. 객체 쿼리 언어로서 쿼리 작업 중 SQL과 다릅니다. 쿼리 문자열의 내용은 클래스 이름과 클래스 속성 이름으로 바꿔야합니다. 이 쿼리 방법은 비교적 간단합니다. SQL 기술이있는 한 HQL을 사용하는 것은 매우 간단합니다. 그러나주의를 기울여야하는 몇 가지 문제가 있습니다. 즉, 데이터 쿼리 및 데이터를 얻는 것이 목적이 아니며, 고려해야 할 것은 효율적인 쿼리 문을 작성하는 방법입니다. 이는 토론의 초점입니다.
1.N+1 문제
(1) N+1 문제는 무엇입니까?
이 명사를 처음 들었을 때 의심이있을 수 있습니다. 나는 전에 n+1 문제에 대해 들어 본 적이 없다. 그래서 그것은 무엇을 의미합니까? n+1은 테이블의 n 데이터를 나타 내기 때문에 이러한 n 데이터를 얻을 때 n+1 sql 명령이 생성됩니다. 이 작업을 N+1이라고합니다. 여기서 1은 ID 목록을 검색하는 명령문을 발행하는 것을 말하고 N은 관련 객체를로드하기 위해 ID를 기반으로 N SQL 문을 발행하는 것을 나타냅니다. 이러한 종류의 쿼리 작업은 매우 비효율적이며 반복자에서 종종 생성됩니다. 즉, 쿼리 결과를 반복자로 직접 변환하면 다음과 같이이 문제가 발생합니다.
public void testQuery () {세션 세션 = null; try {session = hibernateutils.getSession (); session.begintransaction (); /*** N+1 문제가 있습니다. 소위 n+1의 가치는 n+1 sql 문** 1 : ID 목록을 쿼리하는 진술을 발행하는 것입니다** n : ID를 기반으로 exs ql 문을로드하고 관련 객체*/ iterator iter = session.createquery ( "학생"). 반대쪽 (); while (iter.hasnext ()) {학생 학생 = (학생) iter.next (); System.out.println (whity.getName ()); } session.getTransaction (). commit (); } catch (예외 e) {e.printstacktrace (); session.getTransaction (). Rollback (); } 마침내 {hibernateutils.closesession (세션); }}위의 쿼리 코드는 쿼리가 반복자로 반환되므로 N+1 문제가 발생하여 한 번 생성되지 않으면 SQL 문이 발행되도록합니다. 이는 주로 캐시의 데이터를 쿼리하는 반복자의 쿼리 메커니즘에 따라 다릅니다. 캐시에 데이터가 존재하지 않으면 데이터가 먼저 메모리로 변환되므로 현재 SQL 쿼리 문이 발행되므로 SQL 문은 모든 반복이 생성됩니다. 이 글쓰기 방법은 실제로 실수이며 다른 방법을 사용하여 최적화 할 수 있습니다.
(2) N+1 문제를 피하십시오
N+1의 문제는 반복의 부적절한 사용으로 인해 발생합니다. 물론, 다른 방법은 N+1 의이 문제를 피하기 위해 사용될 수 있습니다. 다음은 목록 방법입니다. 목록과 반복의 가장 큰 차이점은 목록이 데이터를 캐시에 넣지 만 캐시를 사용하지 않는다는 것입니다. 기본적으로 List는 매번 SQL 문을 발행합니다. 반복을 사용하기 전에 목록을 사용하여 데이터를 데이터베이스에 저장하여 데이터에 액세스 할 때 캐시에서 읽을 수 있도록 N+1 문제의 발생을 피할 수 있습니다. 코드는 다음과 같습니다.
public void testQuery () {세션 세션 = null; try {session = hibernateutils.getSession (); session.begintransaction (); 목록 학생 = session.createrecer ( "학생에서"). list (); System.out.println("--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 그런 다음 ID를 기반으로 한 SQL 문 쿼리가 발행되지 않으며 캐시의 데이터가 직접 사용됩니다. * * 반복 방법 캐시에 데이터가 존재하면 성능이 향상 될 수 있습니다. 그렇지 않으면 N+1 문제가 발생할 수 있습니다. * // Alias Ierator iter = session.createquery ( "학생"). System.out.println (Student.getName ()); }}위의 예는 목록 작업을 수행 한 후 데이터가 세션 캐시 (1 단계 캐시)에 배치되므로 N+1 문제를 피합니다. 따라서 ITREATE를 사용하면 ID 목록을 쿼리하기 위해 명령문이 발행 된 다음 해당 데이터가 ID에 따라 캐시에로드됩니다. 캐시에 데이터가 일치하는 경우 ID를 기반으로 한 SQL 문 쿼리가 더 이상 발행되지 않으며 캐시의 데이터가 직접 사용됩니다. 캐시에 데이터가 존재하면 반복 방법은 성능을 향상시킬 수 있습니다. 그렇지 않으면 N+1 문제가 발생합니다.
2. 객체 탐색 쿼리
객체 탐색은 한 객체에서 객체의 속성 탐색에 따라 다른 객체에서 데이터를 얻는 것을 말합니다. 쿼리 문을 단순화하고 쿼리 메소드를 최적화 할 수 있습니다. 우리가 평소 아이디어를 따르는 경우, 다른 객체의 작동을 얻기 위해 다른 클래스의 객체를 다시 작성하고 작성할 수 있습니다.
@suppresswarnings ({ "선택 취소", "rawtypes"}) public void testQuery1 () {세션 세션 = null; try {session = hibernateutils.getSession (); session.begintransaction (); // 결과 세트 속성 목록을 반환하고 엔티티 클래스의 요소 유형 및 속성 유형은 동일한 목록입니다. for (iterator item = whity.iterator (); ite.hasnext ();) {Student obj = (Student) ite.next (); System.out.println (obj.getName ()); } session.getTransaction (). commit (); } catch (예외 e) {e.printstacktrace (); session.getTransaction (). Rollback (); } 마침내 {hibernateutils.closesession (세션); }}위의 예제의 쿼리 문은 객체 탐색 메소드를 사용합니다. 쿼리 문은 학생 객체의 정보 쿼리이지만 비교할 객체 속성은 클래스 객체의 이름 속성에서 나옵니다. 현재 객체 탐색 쿼리 메소드를 사용하면 쿼리 효율이 크게 향상되고 쿼리 문을 최적화합니다. 일반적인 쿼리 방법 인 경우 많은 연결 문이 생성 될 수 있으며 이는 매우 복잡합니다.
2. SQL 기본 쿼리
기본 쿼리 값은 SQL 문을 사용하여 HQL 문을 사용하지 않고 쿼리 및 데이터를 얻는 것입니다. 사용 방법은 실제로 HQL과 유사하게 매우 간단합니다. 쿼리에 createSqlQuery 메소드 만 사용하면됩니다. 실제로 HQL의 Createquery 방법과 유사합니다. 코드는 다음과 같습니다.
public void testqeury () {세션 세션 = null; try {session = hibernateutils.getSession (); session.begintransaction (); List List = session.createsqlQuery ( "select * from t_student"). list (); for (iterator item = list.iterator (); ite.hasnext ();) {object [] obj = (Object []) ite.next (); System.out.println (obj [0]+","+obj [1]); } session.getTransaction (). commit (); } catch (예외 e) {e.printstacktrace (); session.getTransaction (). Rollback (); } 마침내 {hibernateutils.closesession (세션); }}위의 코드는 CreateSqlQuery 메소드를 사용합니다. 이 메소드의 쿼리 문자열은 SQL 문입니다. 기본 문자열 쿼리 메소드를 구현합니다. 차이점은 HQL에 또 다른 포장 레이어가 있으며 Hibernate.cfg.xml의 해당 방언 옵션을 구성하여 매핑을 완료한다는 것입니다.
3. 연결 쿼리
연결 쿼리는 종종 SQL에서 여러 객체 모음을 얻는 데 사용됩니다. 그중에서도 가장 일반적으로 사용되는 것은 내부 조인, 왼쪽 조인, 오른쪽 조인 등이 있으며, 여기에는 내부 조인 쿼리, 왼쪽 외부 조인 쿼리 및 오른쪽 외부 조인 쿼리를 나타냅니다. 쿼리 중에 반환하는 내용은 엔티티 간의 직교 제품, 쿼리의 내용 및 왼쪽 테이블의 일부 내용, 쿼리 컨텐츠 및 오른쪽 테이블의 일부 내용이며 쿼리 기능입니다. HQL의 연결 쿼리 방법과 SQL의 연결 쿼리는 쿼리 결과에서 동일하지만 쿼리 문에는 약간의 차이가 있습니다.
1. 내부 연결
HQL의 조인트 쿼리는 내부 조인 명령문 또는 조인 명령문을 사용하여 쿼리 할 수 있으며, 얻은 결과 세트는 직교 제품입니다. SQL-Connection Query와 유사하게 HQL의 조인 쿼리는 명시적이고 암시적인 두 가지 유형으로 나뉩니다. 표시된 쿼리는 쿼리 문자열의 조인 키워드를 나타냅니다. 암시 적 쿼리는 문자열에 가입을 추가 할 필요가 없습니다.
// 내부 연결 @SuppressWarnings ({ "선택 취소", "rawTypes"}) public void testQuery () {세션 세션 = null; try {session = hibernateutils.getSession (); session.begintransaction (); // 결과 세트 속성 목록을 반환하고 엔티티 클래스의 요소 유형 및 속성 유형은 동일한 목록입니다. for (iterator item = whit보지.. irthator (); ite.hasnext ();) {object [] obj = (Object []) ite.next (); System.out.println (obj [0]); } session.getTransaction (). commit (); } catch (예외 e) {e.printstacktrace (); session.getTransaction (). Rollback (); } 마침내 {hibernateutils.closesession (세션); }}
2. 외부 연결
외부 연결은 왼쪽 외부 연결 및 오른쪽 외부 연결 쿼리로 나뉩니다. 쿼리 메소드는 비슷하지만 쿼리 결과는 다릅니다. 그것들은 쿼리 결과에서 SQL의 외부 연결과 동일합니다. 차이점은 작문 방법입니다. 특정 코드는 다음과 같습니다.
@suppresswarnings ({ "선택 취소", "rawtypes"}) public void testQuery () {세션 세션 = null; try {session = hibernateutils.getSession (); session.begintransaction (); // 결과 세트 속성 목록을 반환하고 엔티티 클래스의 요소 유형 및 속성 유형은 동일한 목록입니다. for (iterator item = whit보지.. irthator (); ite.hasnext ();) {object [] obj = (Object []) ite.next (); System.out.println (obj [0]); } session.getTransaction (). commit (); } catch (예외 e) {e.printstacktrace (); session.getTransaction (). Rollback (); } 마침내 {hibernateutils.closesession (세션); }}위의 코드는 왼쪽 외부 조인 쿼리 문을 사용합니다. 해당 오른쪽 외부 조인 쿼리 메소드는 왼쪽 외부 조인과 유사합니다. 왼쪽으로 오른쪽으로 변환하십시오. 쿼리 데이터는 목록 객체에 저장되며 쿼리 내용은 목록을 통해 얻을 수 있습니다.
4. 외부 명명 쿼리
외부 명명 쿼리는 쿼리 문을 매핑 파일에 쓰고 <query> 태그를 사용하여 매핑 파일에서 HQL 문을 정의하는 것을 나타냅니다. 이러한 방식으로 정의 된 HQL 문은 함수 구성 함수를 실현할 수 있습니다. 문제가있는 경우 구성을 수정하면됩니다. 이 SQL 문을 사용하려면 다음 예제에 표시된대로 프로그램의 Session.GetNamedQuery () 메소드를 사용하여 HQL 쿼리 문자열을 가져올 수 있습니다.
1. 외부 쿼리 문
다음 예제는 외부 쿼리 문의 적용을 보여주고 <query> 태그를 매핑 파일에 추가하고 태그에 이름 속성을 추가 한 다음 문자열을 <! [cdata []]>에 추가하여 쿼리의 이름 속성에 따라 해당 쿼리 문자열을 얻을 수 있도록 문자열을 추가하십시오.
<? XML 버전 = "1.0"?> <! DocType Hibernate Mapping Public "-// hibernate/hibernate 매핑 dtd 3.0 // table = "t_student"> <id name = "id"> <generator // id> <property name = "name"/> <property name = "createTime"> </property> <!-한쪽의 학생에게 새 클래스 열을 추가하면 열 이름은 클래스 목록과 동일해야합니다. hbm.xml --> classs "> </moth-to-on </>>> <classid"> <classid "> <classid"> 이름 = "QueryStudent"> <! ]]]> </query> </hibernate-mapping>
외부 이름이 지정된 쿼리는 쿼리 문을 매핑 파일에 넣으므로 공개 쿼리 문자열로 간주 될 수 있습니다. 이것은 다른 프로그램 파일을 얻고 사용할 수 있도록 이점입니다. 또한 공개 문자열로서 수정의 편의성을 향상시킵니다.
2. 프로그램 응용 프로그램
외부 쿼리 문을 정의한 후 프로그램에서이를 사용해야합니다. HQL은 getNameQuery 메소드를 제공하여 외부 쿼리 문자열을 가져옵니다. 이 방법에 외부 커서 이름을 추가해야합니다. HQL은 다음과 같이 커서 이름에 따라 해당 SQL 문 블록을 쿼리합니다.
// 외부 명명 쿼리 @SuppressWarnings ({ "선택 취소", "rawTypes"}) public void testQuery () {세션 세션 = null; try {session = hibernateutils.getSession (); session.begintransaction (); 목록 학생 = session.getNamedQuery ( "QueryStudent"). SetParameter (0, 10) .list (); for (iterator item = whity.ite.hasnext ();) {학생 obj = (학생) ite.next (); System.out.println (obj.getName ()); } session.getTransaction (). commit (); } catch (예외 e) {e.printstacktrace (); session.getTransaction (). Rollback (); } 마침내 {hibernateutils.closesession (세션); }}