지난번에 우리는 기준을 사용하여 관련 작업을 수행하는 방법을 배웠지 만 기준은 최대 절전 모드에서 공식적으로 권장되는 쿼리 방법이 아니기 때문에 많이 사용하지 않습니다. 이제 공식적으로 권장되는 HQL을 살펴보고 그것이 얼마나 강력한 지 알아 봅시다.
HQL 또는 최대 절전 모드 쿼리 문과 SQL의 차이점은 무엇입니까? 한 글자의 차이, 하하.
물론 이것은 사실이 아닙니다. HQL과 SQL의 차이점은 다른 아이디어에 있습니다. HQL은 객체 지향 방향을 사용하여 쿼리를 사용하는 반면 SQL은 2 차원 데이터베이스 테이블에 쿼리를 사용합니다. 여기에 포함 된 것은 아이디어의 차이입니다. HQL은 실제로 SQL이며, 최대 절전 모드는 내부적으로 SQL을 변환하고 생성하도록 만들어집니다.
1) 더 이상 고민하지 않고 그 힘을 살펴 보겠습니다.
사용자로부터
이 코드는 SQL의 테이블 이름에서 자주 사용하기 때문에 매우 친숙하지만 여기서는 사용자가 여기서 테이블 이름이 아니라 엔티티 클래스의 이름이 아니라 최대 절전 모드가 매핑하는 데 도움이된다는 것입니다.
SQL 문서를 연결하십시오. 특정 속성을 찾고 특정 속성에 따라 조건부로 제한하려면 비슷한 문을 얻을 수 있습니다.
USR.age> 20 및 usr.age <60 인 사용자 중 usr.name, usr.age를 선택하십시오.
이런 식으로, 우리는 20 세 이하의 60 세 미만의 사용자의 이름과 나이를 발견했습니다. 이해하기 쉽습니다.
SQL 문의 및, 또는, like, <,>, = 등은 모두 HQL에 사용할 수 있습니다.
여러 속성을 쿼리 할 때 반환 된 결과는 객체 [] 배열이며, 하나의 항목 만 있으면 객체가 반환됩니다. 이를 위해서는 다른 구문 분석 방법이 필요하므로 쿼리 할 때주의를 기울여야합니다.
2) 물론, 우리는 이전에 HQL이 객체 지향적이라고 말했으며,이를 수행하면 객체 지향적 인 아이디어가 아닙니다. 변경하자 :
USR.age> 20 사용자 USR에서 새 사용자 (USR.Name, Usr.age)를 선택하십시오.이런 식으로 쿼리 결과를 사용자 객체에 넣습니다. 사용자 생성기는 여기에서 호출됩니다. 사용자 클래스에서 두 매개 변수를 수신하는 사용자 생성자가 있어야합니다. 그렇지 않으면 오류 가보고됩니다. 오류 메시지는 대략 다음과 같습니다.
클래스에서 적절한 생성자를 찾을 수 없습니다 [org.hibernate.tutorial.domain8.user]
적합한 생성자를 찾을 수 없습니다. 해당 매개 변수를 수신하는 생성자를 추가하는 것은 매우 분명합니다.
해당 ID를 확인했을 때 알지 못했습니다. 현재 SaveOrupDate 메소드를 호출하면 실제로 저장된 작업을 수행했습니다.
테스트 코드를 살펴 보겠습니다.
위의 쿼리 문을 실행 한 후 다음 작업을 수행합니다.
while (iter.hasnext ()) {user user = (user) iter.next (); user.setName ( "sun2"); 세션 .saveorupdate (사용자); } 현재 최대 절전 모드 진술은 다음과 같습니다.
Hibernate : 사용자에 삽입 (user_name, age) 값 (?,?)
업데이트가 아닌 새로운 것을 삽입합니다.
그런 다음 업데이트 해야하는 경우 ID를 함께 찾아야합니다.
USR.age> (USR에서 avg (usr.age)를 선택하십시오.
사용자 생성자를 수정해야합니다.
현재 테스트 코드를 다시 실행하면 다음과 같습니다.
Hibernate : 사용자 세트 User_Name =?, age =? 여기서 user_id =?
Usr.age> (USR에서 avg (usr.age) select usr.
이 HQL은 평균 연령보다 나이가 많은 사용자의 이름을 감지합니다.
4) Hibernate 3에서는 먼저로드 한 다음 2에서 삭제하지 않고도 객체를 쉽게 업데이트하고 삭제할 수 있습니다. 하나의 문서에서 직접 수행 할 수 있습니다.
사용자 세트 이름 = '123123'여기서 이름 = 'sun33'
삭제 명령문은 비슷합니다.
이름 = '123123'을 삭제합니다.
5) 또한 최대 절전 모드로 그룹화하고 정렬하는 것도 쉽습니다. 그룹을 사용하고 주문하면 지금은 더 이야기하지 않을 것입니다.
6) 위의 내용은 쿼리 또는 업데이트에 직접 기록되어 있음을 알 수 있습니다. 동적 할당이 필요하거나 과제가 너무 많으면 JDBC와 같은 문자열을 스플릿 할 수 없습니다. 5 명 이상이 있고 프로젝트 팀의 모든 사람들이 나를 꾸짖고 싶어합니다.
현대적인 방법을 사용하고 대신 자리 표시자를 사용한 다음 특정 값을 설정하는 것이 좋습니다.
우리의 직접 코드 :
query query = session.createquery ( "usr.name =?") usr usr에서 새 사용자 (usr.name, usr.age, usr.id)를 선택합니다. Query.setString (0, "Shun");
우리는이 방법이 직접 사용하는 준비된 상태와 유사하다는 것을 알 수 있습니다. 그것은 set ***를 통해 설정되지만 차이점은 여기서 위치가 0에서 시작되며 준비된 상태는 1부터 시작되므로 여기에서 특별한주의를 기울입니다.
Hibernate2에는 세션이 있습니다. 그러나 지금은 3을 사용하기 때문에 그에 대해별로 말하지 않을 것입니다.
위에서 우리가 사용한 자리 표시자는 주문 자리 표시 자라고하며, 참조 자리 표시 자라고 불리는 또 다른 것이 있습니다. 봅시다 :
query query = session.createquery ( "usr.name = : name"usr usr usr에서 새 사용자 (usr.name, usr.age, usr.id)를 선택합니다. query.setparameter ( "name", "shun");
나는 우리의 HQL 진술에 이름이있는 것을 보았다. 이것은 참조 자리 표시 자입니다. 나중에 setParameter를 통해만 값을 설정하면됩니다. 여기서 첫 번째 매개 변수는 HQL 문의 자리 표시 자 값에 해당해야합니다.
물론 어떤 사람들은 이것이 객체 지향적이지 않다고 말할 수 있으므로 다시 객체 지향으로 가자.
먼저, 우리가 쿼리하는 값을 캡슐화 할 클래스를 만듭니다.
공개 클래스 userQuery {개인 문자열 이름; 사적인 int 연령; // get/set method} query query = session.createquery ( "usr.name = : name"user usr에서 새 사용자 (usr.name, usr.age, usr.id)를 선택하십시오. UserQuery uq = new userQuery (); uq.setname ( "shun"); query.setProperties (UQ); 이 클래스를 통해 직접 쿼리 해야하는 값을 캡슐화합니다. 매우 객체 지향적입니다.
일부 프로젝트 팀에는 SQL 문이 코드에 표시되지 않는 이상한 규정이 있습니다. 이것이 사양이라면, 내가 본 회사의 모든 코드는 자격이 없습니다. 컵에 많은 끈 스 플라이 싱으로 인해 우울해 보입니다. 기존 프로젝트를 유지하기 위해 상처 받기가 정말 어렵습니다.
코드에는 SQL 문이 허용되지 않습니다. 이것은 좋은 제안이지만, 행사에 달려 있습니다. 최대 절전 모드가 파일 매핑에서 HQL을 구성하는 방법을 살펴 보겠습니다.
구성 파일을 직접 살펴보십시오.
<query name = "querybyname"> <! [cdata [usr.name = : name]> </query>
우리는 이와 같은 태그를 추가했는데, 이것은 그것이 HQL 문임을 나타냅니다.
이 진술을 가져와야 할 때는 코드에 문장을 추가하면됩니다.
query query = session.getNamedQuery ( "QueryByName");
이런 식으로, HQL 진술이 얻어진다.
HQL은 내부 조인, 왼쪽 외부 결합, 오른쪽 외부 조인, 전체 조인과 같은 SQL의 조합을 사용하여 쿼리 할 수 있습니다.
사용법을 살펴 보겠습니다.
먼저 엔티티 클래스, 테스트에서 사용해야 할 사항을 살펴 보겠습니다.
공개 클래스 턱시기는 시리얼이 가능성 {private static final long serialversionuid = 1L; 개인 int ID; 사적인 int 연령; 개인 문자열 이름; 비공개 세트 <dassching> 주소 = New Hashset <dassching> (); // get/set method를 생략} 공개 클래스 주소는 시리얼이즈 가능 {private static final long serialversionuid = 1l; 개인 int ID; 개인 문자열 주소; 비공개 엄부개 사용자; // GET/SET Method를 생략} 매핑 파일을 살펴 보겠습니다.
<hibernate-mapping package = "org.hibernate.tutorial.domain6"> <class name = "tuser"table = "t_user"dynamic-insert = "true"dynamic-update = "true"> <id name = "id"column = "id"> <generator/> </id> 이름 = "age"type = "java.lang.integer"열 = "age"/> <set name = "주소"cascade = "all"table = "t_address"inverse = "true"> <key column = "user_id"/> <one-to-many/</set> </class> </hibernate-mapping> <hibernate-mappe package = "org.hibernate.tutorial.domain6"> <class name = "address"table = "t_address"dynamic-Insert = "false"dynamic-update = "false"dynamic-update = "false"dynamic-update = "id"type = "java.lang.integer"< /id> <속성 이름 = "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" type = "java.lang.string"/> <oniver-one name = "user"column = "user_id"nont-null = "true"> </hibernate-mapping> </hibernate-mapping>
해당 패키지 이름을 수정하면됩니다.
공식 테스트를 수행합시다.
테스트하기 전에 테이블의 데이터를 살펴 보겠습니다.
t_address 테이블의 데이터는 다음과 같습니다.
t_user 테이블 데이터는 다음과 같습니다.
1) 먼저, 내부 조인을 살펴 보겠습니다. 내부 결합을 살펴 보겠습니다. 여기서 가져 오는 의미는 필요한 데이터를 가져 오는 것입니다. 페치를 사용하지 않으면 우리가 가져온 데이터는 객체 [] 데이터 유형입니다.
먼저 살펴 보겠습니다
Tuser USR Inner Join Fetch Fetch USR.Addresses
우리가 그것을 실행할 때, 우리는 최대 절전 모드 출력이 다음과 같습니다.
Hibernate : tuser0_.id로 id1_0_, address1_.id as id0_1_, tuser0_.name as name1_0_, tuser0_.age as Age1_0_, addressS1_.Address as address0_1_, asseres1_.user as adress3_0_1_, inter3_0_1_, id0 _. tuser0_.id = address1_.user_id에서 t_address jesdreses1_
MySQL에서 실행될 때 결과를 볼 수 있습니다.
최대 절전 모드가 내부 조인 명령문으로 변환하고 주소를 찾는다는 것을 알 수 있습니다.
해당 주소와 레코드가 없기 때문에 결과에 Shun4에 대한 기록이 없음을 알 수 있습니다.
페치 대신 내부 조인을 사용하면 인쇄 된 진술은 다음과 같습니다.
Hibernate : tuser0_.id as is1_0_, address1_.id as id0_1_, tuser0_.name as name1_0_, tuser0_.age as agesses1_0_, address0_1_, addresss1_.user_id tuser tuser tuser join tuset to join to join join join to join join join tuser join | tuser0_.id = address1_.user_id
진술은 다르지 않은 것 같습니다. 그러나 우리가 그것을 찾으면 객체 [] 배열 유형을 가져 오 므로이 분석에주의를 기울여야합니다.
Fetch를 사용하지 않고 내부 조인 만 사용하면 다음과 같이 구문 분석해야합니다.
query query = session.createquery ( "Tuser Usr Inner join usr.addresses"); 목록 List = Query.list (); 반복자 iter = list.iterator (); while (iter.hasnext ()) {object [] results = (Object []) iter.next (); for (int i = 0; i <results.length; i ++) {system.out.println (results [i]); }} 인쇄 결과를 볼 수 있습니다.
org.hibernate.tutorial.domain6.tuser@16925b0 org.hibernate.tutorial.domain6.address@914f6a org.hibernate.tutorial.domain6.tuser@787d6a org.hibernate.tutorial6.address@71dc3d org.hibernate.tutorial.domain6.tuser@1326484 org.hibernate.tutorial.domain6.address@16546ef
각 결과는 해당 객체입니다.
2) 왼쪽 외부 조인, 이것은 SQL의 왼쪽 연결과 동일합니다. 예제를 직접 살펴 보겠습니다.
Tuser에서 USR 왼쪽 외부 조인 Fetch USR.addresses
위의 진술을 실행하면 최대 절전 모드가 인쇄됩니다.
Hibernate : tuser0_.id로 id1_0_, address1_.id as id0_1_, tuser0_.name as name1_0_, tuser0_.age as Age1_0_, assend tuser0_.id = address1_.user_id에서 t_address address1_에 가입하십시오
MySQL에서 확인하고 다음을 보았습니다.
우리는 Shun4에 상응하는 흡입이 없지만 여전히 발견된다는 것을 알 수 있습니다. 왼쪽 외부 조인은 왼쪽 테이블에서 모든 레코드를 찾는 것을 말합니다.
나는 여기서 가져 오지 않고 상황에 대해 이야기하지 않을 것입니다.
3) 다음으로 오른쪽 외부 조인을 살펴 보겠습니다. 이름에서 판단하면 왼쪽 외부 조인과 관련이 있어야합니다. 우리는 예제를 직접 보면서 명확하게 볼 수 있습니다.
Tuser USR 오른쪽 외부 조인 Fetch USR.addresses
우리는 그것을 실행하고 최대 절전 모드에서 결과 문을 얻습니다.
Hibernate : tuser0_.id로 id1_0_, address1_.id as id0_1_, tuser0_.name as name1_0_, tuser0_.age as Age1_0_, addressS1_.Address as Address0_1_, asseres1_.user right of right of as adress3_0_1_, tuser _. tuser0_.id = address1_.user_id에서 t_address address1_에 가입하십시오MySQL에서 실행 한 후 결과를 볼 수 있습니다.
여기서 우리는 주소가 test4이고 해당 사용자가 해당하는 사용자가 없지만 여전히 발견됩니다. 오른쪽 외부 조인은 오른쪽 테이블에서 모든 레코드를 찾는 것을 의미합니다.
Fetch의 상황은 위와 같습니다. 이해하지 못하면 내부 가입 Fetch를 살펴볼 수 있습니다.