반응형
JOIN
http://docs.jboss.org/hibernate/stable/core/api/org/hibernate/Criteria.html
부서와 사원의 1:n 관계에 JOIN 쿼리를 날려봅시다.
원래 하이버네이트에서는 매핑을 잘 맺어주면, 단순 getter 로도 관계를 가지는 테이블의 내용을 가져올 수 있습니다.
이렇게하면 사원에 해당하는 부서의 정보를 가져올 수 있습니다.
로그를 보면 select문이 여러번 출력되는 것을 볼 수 있습니다.
List<Emp> emps = crit.list(); 에서 ' select empno, ename, job, hire_date from tbl_emp; ' 쿼리가 실행되고,
dept.getDeptName(); 에서 사원의 부서번호에 따라 ' select deptno, dname, loc from tbl_dept; ' 쿼리가 실행 됩니다.
부서의 종류가 엄청나게 많다면 두번째 select 쿼리가 많이 실행 되게 될 것입니다.
쿼리를 할때 최소한의 I/O로 실행되게 하고, 뭐.. 서브쿼리보다는 조인이 빠르고 흘러가면서 들은 것들이 있기 땜시... JOIN ㄱㄱ
INNER JOIN
키를 기준으로 일치하는 데이터만 가져옵니다. (다 아시졍? +_+)
Criteria crit = sess.createCriteria(Emp.class);
Session.createCriteria(클리스명) 를 통해서 생성한 Critereria 객체에 다시 createCriteria(String associationPath, String alias) 를 사용해서 JOIN 을 하면 됩니다.
이렇게 JOIN 한 결과는 Emp 객체도 Dept 객체도 아니기 때문에, Criteria의 setResultTransformer 메소드를 사용하여 Criteria를 이용한 조회 결과를 별도 정의한 객체 형태나 Map 형태로로 전달받아야 하겠습니다.
근데 전 객체로 변형하는 법은 잘 안되서... 걍 Map 으로 ㄱㄱㄱ!
여기서 두번째 인자로 넣는 엘리어스명은 쿼리에서 쓰는 엘리어스명도 되지만 나중에 Map 에서 꺼 낼때의 키도 되기 때문에 꼭 지정해줘야 할 것입니다....
실행 되는 쿼리는 아래와 같습니다.
이러면 당연히 부서가 없는 'TOM' 은 목록에 나오지가 않겠죠? 만약 사원 목록을 본다면 부서가 없는 사원이 나오면 안되겠죠?
LEFT JOIN
두개의 테이블을 조인할 때 왼쪽 테이블을 기분으로 오른쪽 테이블을 조인 시키는 LEFT JOIN 을 해봅시다...
createCriteria(String associationPath, String alias, int joinType) 를 사용하면 됩니다.
실행되는 쿼리는 아래와 같습니다. 엘리어스 사용에 주의 하세요~
※ RIGHT JOIN 은 없네요 테이블의 좌 우 를 바꾸셔요~ 히힛
간단하게 사원명과 부서명으로 조회하는 페이지 만들어 봤어요~
Pagination
많은 자료를 조회할 때 일정한 양의 자료를 한 페이지만 보여주도록 하는 기능입니다.
꼭 필요한 기능이고, 그다지 복잡할 것도 없지만, 막상 쿼리 날리려면 DBMS 마다 쿼리도 틀리고... 쉽지 안쵸 ㅠ_ㅠ
하지만 하이버네이트에서는
setFirstResult(int firstResult) 과 setMaxResults(int maxResults) 메소드 두개면 해결 됩니다! ㅋㅋㅋ
전부터 해오던 우편번호 테이블 가지고 해봅시다...
한 페이지에 10개씩 보여준다고 하고 4페이지의 내용을 보여주게 됩니다.
페이징 처리가 되있는 우편번호 검색 페이지를 만들어봤습니다.
몇개의 DMBS 에서 돌려보니까 아래와 같은 쿼리가 나오네요
MySQL 5.1.38
Oracle 10g Express Edition
Microsoft SQL Server 2005
MSSQL 은 일단 페이지번호 * 갯수 만큼 가져와서 내부적으로 처리를 하나봐요.....
http://blog.naver.com/oyukihana?Redirect=Log&logNo=60002506896
http://docs.jboss.org/hibernate/stable/core/api/org/hibernate/Criteria.html
부서와 사원의 1:n 관계에 JOIN 쿼리를 날려봅시다.
원래 하이버네이트에서는 매핑을 잘 맺어주면, 단순 getter 로도 관계를 가지는 테이블의 내용을 가져올 수 있습니다.
Criteria crit = sess.createCriteria(Emp.class);
List<Emp> emps = crit.list();
int size = emps.size();
for(int i=0 ; i < size ; i++) {
Emp emp = emps.get(i);
Dept dept = emp.getDept();
String empName = emp.getName();
String deptName = dept != null ? dept.getDeptName() : "";
System.out.println("row: " + (i+1));
System.out.println(emp);
System.out.println(dept);
}
List<Emp> emps = crit.list();
int size = emps.size();
for(int i=0 ; i < size ; i++) {
Emp emp = emps.get(i);
Dept dept = emp.getDept();
String empName = emp.getName();
String deptName = dept != null ? dept.getDeptName() : "";
System.out.println("row: " + (i+1));
System.out.println(emp);
System.out.println(dept);
}
이렇게하면 사원에 해당하는 부서의 정보를 가져올 수 있습니다.
로그를 보면 select문이 여러번 출력되는 것을 볼 수 있습니다.
List<Emp> emps = crit.list(); 에서 ' select empno, ename, job, hire_date from tbl_emp; ' 쿼리가 실행되고,
dept.getDeptName(); 에서 사원의 부서번호에 따라 ' select deptno, dname, loc from tbl_dept; ' 쿼리가 실행 됩니다.
부서의 종류가 엄청나게 많다면 두번째 select 쿼리가 많이 실행 되게 될 것입니다.
쿼리를 할때 최소한의 I/O로 실행되게 하고, 뭐.. 서브쿼리보다는 조인이 빠르고 흘러가면서 들은 것들이 있기 땜시... JOIN ㄱㄱ
INNER JOIN
키를 기준으로 일치하는 데이터만 가져옵니다. (다 아시졍? +_+)
// select * from tbl_emp e
Criteria crit = sess.createCriteria(Emp.class, "e");
// join tbl_dept d on this.deptno = d.deptno
crit.createCriteria("dept", "d");
// Result 를 Map 형태로 변환
crit.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List<Map<String, Object>> joinList = crit.list();
int size = joinList.size();
for(int i=0 ; i < size ; i++) {
Map<String, Object> map = joinList.get(i);
Emp emp = (Emp) map.get("e");
Dept dept = (Dept) map.get("d");
System.out.println("row: " + (i+1));
System.out.println(emp);
System.out.println(dept);
}
Criteria crit = sess.createCriteria(Emp.class, "e");
// join tbl_dept d on this.deptno = d.deptno
crit.createCriteria("dept", "d");
// Result 를 Map 형태로 변환
crit.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List<Map<String, Object>> joinList = crit.list();
int size = joinList.size();
for(int i=0 ; i < size ; i++) {
Map<String, Object> map = joinList.get(i);
Emp emp = (Emp) map.get("e");
Dept dept = (Dept) map.get("d");
System.out.println("row: " + (i+1));
System.out.println(emp);
System.out.println(dept);
}
Criteria crit = sess.createCriteria(Emp.class);
Session.createCriteria(클리스명) 를 통해서 생성한 Critereria 객체에 다시 createCriteria(String associationPath, String alias) 를 사용해서 JOIN 을 하면 됩니다.
이렇게 JOIN 한 결과는 Emp 객체도 Dept 객체도 아니기 때문에, Criteria의 setResultTransformer 메소드를 사용하여 Criteria를 이용한 조회 결과를 별도 정의한 객체 형태나 Map 형태로로 전달받아야 하겠습니다.
근데 전 객체로 변형하는 법은 잘 안되서... 걍 Map 으로 ㄱㄱㄱ!
여기서 두번째 인자로 넣는 엘리어스명은 쿼리에서 쓰는 엘리어스명도 되지만 나중에 Map 에서 꺼 낼때의 키도 되기 때문에 꼭 지정해줘야 할 것입니다....
실행 되는 쿼리는 아래와 같습니다.
select
this_.empno as empno0_1_,
this_.ename as ename0_1_,
this_.job as job0_1_,
this_.hire_date as hire4_0_1_,
this_.deptno as deptno0_1_,
d1_.deptno as deptno1_0_,
d1_.dname as dname1_0_,
d1_.loc as loc1_0_
from
tbl_emp this_
inner join
tbl_dept d1_
on this_.deptno=d1_.deptno
this_.empno as empno0_1_,
this_.ename as ename0_1_,
this_.job as job0_1_,
this_.hire_date as hire4_0_1_,
this_.deptno as deptno0_1_,
d1_.deptno as deptno1_0_,
d1_.dname as dname1_0_,
d1_.loc as loc1_0_
from
tbl_emp this_
inner join
tbl_dept d1_
on this_.deptno=d1_.deptno
이러면 당연히 부서가 없는 'TOM' 은 목록에 나오지가 않겠죠? 만약 사원 목록을 본다면 부서가 없는 사원이 나오면 안되겠죠?
LEFT JOIN
두개의 테이블을 조인할 때 왼쪽 테이블을 기분으로 오른쪽 테이블을 조인 시키는 LEFT JOIN 을 해봅시다...
createCriteria(String associationPath, String alias, int joinType) 를 사용하면 됩니다.
// select * from tbl_emp e
Criteria crit = sess.createCriteria(Emp.class, "e");
// join tbl_dept d on this.deptno = d.deptno
crit.createCriteria("dept", "d", Criteria.LEFT_JOIN);
// Result 를 Map 형태로 변환
crit.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List<Map<String, Object>> joinList = crit.list();
int size = joinList.size();
for(int i=0 ; i < size ; i++) {
Map<String, Object> map = joinList.get(i);
Emp emp = (Emp) map.get("e");
Dept dept = (Dept) map.get("d");
System.out.println("row: " + (i+1));
System.out.println(emp);
System.out.println(dept);
}
Criteria crit = sess.createCriteria(Emp.class, "e");
// join tbl_dept d on this.deptno = d.deptno
crit.createCriteria("dept", "d", Criteria.LEFT_JOIN);
// Result 를 Map 형태로 변환
crit.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List<Map<String, Object>> joinList = crit.list();
int size = joinList.size();
for(int i=0 ; i < size ; i++) {
Map<String, Object> map = joinList.get(i);
Emp emp = (Emp) map.get("e");
Dept dept = (Dept) map.get("d");
System.out.println("row: " + (i+1));
System.out.println(emp);
System.out.println(dept);
}
실행되는 쿼리는 아래와 같습니다. 엘리어스 사용에 주의 하세요~
select
this_.empno as empno0_1_,
this_.ename as ename0_1_,
this_.job as job0_1_,
this_.hire_date as hire4_0_1_,
this_.deptno as deptno0_1_,
d1_.deptno as deptno1_0_,
d1_.dname as dname1_0_,
d1_.loc as loc1_0_
from
tbl_emp this_
left outer join
tbl_dept d1_
on this_.deptno=d1_.deptno
this_.empno as empno0_1_,
this_.ename as ename0_1_,
this_.job as job0_1_,
this_.hire_date as hire4_0_1_,
this_.deptno as deptno0_1_,
d1_.deptno as deptno1_0_,
d1_.dname as dname1_0_,
d1_.loc as loc1_0_
from
tbl_emp this_
left outer join
tbl_dept d1_
on this_.deptno=d1_.deptno
※ RIGHT JOIN 은 없네요 테이블의 좌 우 를 바꾸셔요~ 히힛
간단하게 사원명과 부서명으로 조회하는 페이지 만들어 봤어요~
Pagination
많은 자료를 조회할 때 일정한 양의 자료를 한 페이지만 보여주도록 하는 기능입니다.
꼭 필요한 기능이고, 그다지 복잡할 것도 없지만, 막상 쿼리 날리려면 DBMS 마다 쿼리도 틀리고... 쉽지 안쵸 ㅠ_ㅠ
하지만 하이버네이트에서는
setFirstResult(int firstResult) 과 setMaxResults(int maxResults) 메소드 두개면 해결 됩니다! ㅋㅋㅋ
전부터 해오던 우편번호 테이블 가지고 해봅시다...
Criteria crit = sess.createCriteria(Zipcode.class);
crit.setFirstResult(40); // 시작 로우 라인 번호(?)
crit.setMaxResults(10); // 시작 로우 라인 번호로 부터 몇개?!
List<Zipcode> list = crit.list();
int size = list.size();
for(int i=0 ; i < size ; i++) {
Zipcode z = list.get(i);
System.out.println(z.toString());
}
crit.setFirstResult(40); // 시작 로우 라인 번호(?)
crit.setMaxResults(10); // 시작 로우 라인 번호로 부터 몇개?!
List<Zipcode> list = crit.list();
int size = list.size();
for(int i=0 ; i < size ; i++) {
Zipcode z = list.get(i);
System.out.println(z.toString());
}
한 페이지에 10개씩 보여준다고 하고 4페이지의 내용을 보여주게 됩니다.
페이징 처리가 되있는 우편번호 검색 페이지를 만들어봤습니다.
몇개의 DMBS 에서 돌려보니까 아래와 같은 쿼리가 나오네요
MySQL 5.1.38
select
this_.seq as seq0_0_,
this_.zipcode as zipcode0_0_,
this_.sido as sido0_0_,
this_.gugun as gugun0_0_,
this_.dong as dong0_0_,
this_.ri as ri0_0_,
this_.bldg as bldg0_0_,
this_.st_bunji as st8_0_0_,
this_.ed_bunji as ed9_0_0_
from
tbl_zipcode this_ limit ?,
?
this_.seq as seq0_0_,
this_.zipcode as zipcode0_0_,
this_.sido as sido0_0_,
this_.gugun as gugun0_0_,
this_.dong as dong0_0_,
this_.ri as ri0_0_,
this_.bldg as bldg0_0_,
this_.st_bunji as st8_0_0_,
this_.ed_bunji as ed9_0_0_
from
tbl_zipcode this_ limit ?,
?
Oracle 10g Express Edition
select
*
from
( select
row_.*,
rownum rownum_
from
( select
this_.seq as seq0_0_,
this_.zipcode as zipcode0_0_,
this_.sido as sido0_0_,
this_.gugun as gugun0_0_,
this_.dong as dong0_0_,
this_.ri as ri0_0_,
this_.bldg as bldg0_0_,
this_.st_bunji as st8_0_0_,
this_.ed_bunji as ed9_0_0_
from
tbl_zipcode this_ ) row_
where
rownum <= ?
)
where
rownum_ > ?
*
from
( select
row_.*,
rownum rownum_
from
( select
this_.seq as seq0_0_,
this_.zipcode as zipcode0_0_,
this_.sido as sido0_0_,
this_.gugun as gugun0_0_,
this_.dong as dong0_0_,
this_.ri as ri0_0_,
this_.bldg as bldg0_0_,
this_.st_bunji as st8_0_0_,
this_.ed_bunji as ed9_0_0_
from
tbl_zipcode this_ ) row_
where
rownum <= ?
)
where
rownum_ > ?
Microsoft SQL Server 2005
select
top 20 this_.seq as seq0_0_,
this_.zipcode as zipcode0_0_,
this_.sido as sido0_0_,
this_.gugun as gugun0_0_,
this_.dong as dong0_0_,
this_.ri as ri0_0_,
this_.bldg as bldg0_0_,
this_.st_bunji as st8_0_0_,
this_.ed_bunji as ed9_0_0_
from
tbl_zipcode this_
top 20 this_.seq as seq0_0_,
this_.zipcode as zipcode0_0_,
this_.sido as sido0_0_,
this_.gugun as gugun0_0_,
this_.dong as dong0_0_,
this_.ri as ri0_0_,
this_.bldg as bldg0_0_,
this_.st_bunji as st8_0_0_,
this_.ed_bunji as ed9_0_0_
from
tbl_zipcode this_
MSSQL 은 일단 페이지번호 * 갯수 만큼 가져와서 내부적으로 처리를 하나봐요.....
http://blog.naver.com/oyukihana?Redirect=Log&logNo=60002506896
반응형
'Framework > Hibernate' 카테고리의 다른 글
PK 두개 이상시 매핑 (2) | 2009.12.24 |
---|---|
Reverse Engineering (0) | 2009.12.24 |
Hibernate 시작하기 (0) | 2009.12.23 |
Criteria 사용하여 질의 하기 #1 (4) | 2009.09.10 |
다대다(n:m) 관계 설정하기 (0) | 2009.09.02 |
일대다(1:n) 관계 설정하기 (1) | 2009.08.31 |
일대일(1:1) 관계 설정하기 (0) | 2009.08.27 |
하이버네이트(Hibernate) 사용하기 (6) | 2009.08.24 |