'iterate()'에 해당되는 글 2건

  1. 2008.04.13 HQL - join
  2. 2008.04.13 HQL - API

HQL - join

Hibernate 2008.04.13 02:06
from 절에서 내부조인
from Seller s join s.items i where i.price > 1000
많은 의미가 담겨 있고 주의할 점도 있으므로 하나씩 알아 보겠습니다.
1) from 절에서 Seller 객체와 연관 컬렉션 객체인 items 를 내부조인 했습니다.
2) 조인한 상태에서 컬렉션 객체의 alias인 i를 통해 dot(.)으로 프로퍼티에 접근하여 조건을 주었습니다.
3) 2에서 i의 의미는 컬렉션 타입의 객체 자체가 아니라 컬렉션에 들어가는 하나의 Item 입니다.
4) 조회된 결과는 이런 형태일 것 입니다.

보기

5) Seller 객체와 Item 객체가 하나의 행으로써 조회 되기 때문에 Seller 객체가 중복 됩니다.
6) 돌려받은 리스트에 들어있는 객체는 Object 배열로써 Seller와 Item 객체가 담겨 있습니다.

보기

7) 5에서 밝혔다 시피 객체가 중복 됩니다. 그리고 결과 리스트에 조인된 Item 객체까지 포함됩니다.
8) 아래 두 hql은 동일 합니다. (select 절은 따로 자세히 알아 보겠습니다.)
from Seller s join s.items i where i.price > 1000
select s, i from Seller s join s.items i where i.price > 1000
9) 1000원 이상의 제품만 판매하는 판매자의 리스트만 중복없이 조회하고 싶다면 이렇게 수정 합니다.
select distinct s from Seller s join s.items i where i.price > 1000
10) 이제 결과 리스트에는 중복 없는 Seller 객체만 담겨 있습니다.

보기

from 절에서 외부조인
from Seller s left join s.items i with i.price > 1000
외부조인을 사용하기 위한 키워드는 SQL의 그것과 동일 합니다.
하지만 외부 조인 객체의 조건을 where절이 아닌 with절에 주었다는것에 주목해야 합니다.
with는 외부조인시 외부조인 객체에 조건을 줄 때 사용하는 HQL의 특별한 키워드 입니다.

with 사용시 결과

만약 where절에 조건을 주었다면 내부조인과 다를 것이 없었을 것입니다.

where 사용시 결과


자동 조인
1-1 또는 n-1 관계일 경우 join 키워드를 사용하지 않더라도 dot(.)으로 접근하여 조건을 지정할 수 있습니다.
1-1 관계에서의 조인

from Article a where a.detail.content = :content

n-1 관계에서의 조인
from Comment c where c.article.title = :title

where 절에서 조인
from 절에서 했던 조인은 where 절에서도 할 수 있습니다.
프로퍼티를 생략하면 객체의 식별값을 비교합니다. 따라서 아래 두 hql은 동일 합니다.
from Seller s, Item i where i.seller = s
from Seller s, Item i where i.seller.id = s.id

연관 관계가 없는 객체끼리도 where 절에서 조인을 할 수 있습니다.
from Article a, Seller i where a.writer = i.name

조인에서 페이징
다음 hql은 페이징시 문제가 발생 합니다.
from Seller s join s.items
문제가 발생하는 이유는 조회되는 행들에서 Seller 객체가 중복되기 때문에 원하는 결과가 나오지 않습니다.
따라서 select 절에서 특정 객체만 조회하면서 중복을 제거해야 원하는 결과가 나옵니다.
select distinct s from Seller s join s.items

조인에서 iterate()
from Seller s join s.items
위 hql로 iterate() 메서드를 호출하면 Seller의 식별값과 Item의 식별값만 가져오는 SQL이 수행 됩니다.
매우 정상적이죠... 하지만 select 절을 사용하는 순간 결과는 삐뚤어 집니다.
아래 hql로 iterate() 메서드를 호출하면 말도 안되는 SQL이 실행되니 조인 상황에서 iterate() 메서드 사용시 조심해야 겠습니다.
select s from Seller s join s.items
select distinct s from Seller s join s.items

말도 안되는 SQL 보기



신고

'Hibernate' 카테고리의 다른 글

HQL - fetch  (0) 2008.04.13
HQL - select 절  (0) 2008.04.13
HQL - join  (0) 2008.04.13
HQL - where 절  (0) 2008.04.13
HQL - 시작, from 절  (0) 2008.04.13
HQL - API  (0) 2008.04.13
Posted by 째코

HQL - API

Hibernate 2008.04.13 02:04
session.createQuery("hql...") 메서드는 hql 질의를 위한 Query 타입의 객체를 생성합니다.
이제 돌려 받은 Query 타입의 객체로부터 질의를 수행할 수 있습니다.

list() 메서드를 이용해 하나 이상의 객체를 조회할 수 있습니다.
Query query = session.createQuery("from Article");
List<Article> list = query.list();

페이징도 아주 간단 합니다.
Query query = session.createQuery("from Article");
query.setFirstResult(0);
query.setMaxResult(20);
List<Article> list = query.list();
setFirstResult() 메서드의 인자는 첫번째 행을 0부터 시작합니다.
setMaxResult() 메서드의 인자는 가져올 행의 수 입니다.

또는 단 하나의 객체만 조회할 수 도 있습니다.
Query query = session.createQuery("from Article a where a.id = 5");
Article article = (Article)query.uniqueResult();

JDBC 스타일의 ?(위치 파라미터)도 지원 합니다.
Query query = session.createQuery("from Article a where a.id = ?");
query.setInt(0, 5);
JDBC의 그것과 다를 것 없이 메서드들이 너무나 친숙 합니다.
다른점이 있다면 JDBC의 파라미터 인덱스는 1부터 시작하지만 hql에서는 0부터 시작 합니다.

명명된 파라미터는 ?(위치 파라미터)보다 더 직관적 입니다.
Query query = session.createQuery("from Article a where a.id = :id");
query.setInt("id", 5);
순서에 영향을 받지 않고 동일한 파라미터에 대해 모두 적용되며 쿼리문 자체로 문서 역할을 해줍니다.

파라미터 설정을 위한 또 다른 메서드 입니다.

setParameter(String name, Object val)
첫번째 인자는 명명된 파라미터, 두번째 인자는 값 입니다. 타입은 하이버네이트가 판단 합니다.
setParameter(String name, Object val, Type type)
위 메서드와 동일하며 세번째 인자로 타입을 지정하는데 지정되는 타입들은 Hibernate 클래스에 상수로 정의되어 있습니다.

객체지향 쿼리인 만큼 파라미터에 엔티티를 설정 할 수 있습니다.
Member member = session.get(Member.class, 1);
Query query = session.createQuery("from Article a where a.member = :member);
query.setEntity("member", member);
List<Article> list = query.list();
조회를 하면 select ... from Article a where a.memberid = ? 형태의 쿼리가 수행 됩니다.

엔티티 대신 엔티티의 프로퍼티들을 설정 할 수도 있습니다.
Article article = (Article)session.get(Article.class, 1);
Query query = session.createQuery("from Article a where a.title = :title and a.date = :date");
query.setProperties(article);

엔티티가 아닌 프로퍼티들을 조회할 수 있습니다.
Query query = session.createQuery("select id, title from Article");
List<Object []> list = query.list();
for (Object[] row : list) {
    System.out.println(row[0]);
    System.out.println(row[1]);
}
Object 배열을 리스트로 돌려 준다는걸 명심해야 합니다.

캐쉬를 활용할 수 있습니다.
list() 메서드는 수행할 때마다 DB에서 객체의 모든 프로퍼티를 조회하는 반면
iterate() 메서드는 객체의 식별 값만 조회 한다는 차이가 있습니다. 식별 값만 조회하는 이유는 1, 2차 캐쉬를 이용하기 위해서 입니다.
Query query = session.createQuery("from Article");
Iterator<Article> iter = query.iterate();
while (iter.hasNext()) {
    Article article = iter.next();
    System.out.println(article.getTitle());
}
iter.next() 로 리턴되는 객체는 1, 2차 캐쉬에 존재한다면 캐쉬에 있는 객체를 리턴하고
캐쉬에 없다면 식별자 값을 가지고 있는 프록시 객체를 리턴 하고 프로퍼티 사용 시점에 데이터를 조회 합니다.
한번 열려진 iterator 는 모든 행을 읽거나 Session이 종료될 때까지 열려 있게 되는데 명시적으로 Hibernate.close(iter) 메서드를 통해 닫을 수 있습니다.

스크롤 할 수 있습니다.
scroll() 메서드는 JDBC의 스크롤 가능한 ResultSet과 동일한 기능을 수행하는 ScrollableResults 객체를 리턴 합니다.
Query query = session.createQuery("from Article");
ScrollableResults scroll = query.scroll();
주요 메서드는 생략 하겠습니다.

코드를 줄일 수 있습니다.
Query 인터페이스의 파라미터 설정 메서드들은 모두 자기 자신을 리턴 합니다.
따라서 이런 식으로 코드를 줄일 수 있습니다.
Article aritlce = (Article)session.createQuery("from Article a where a.id = ?")
                        .setInt(0, 5).uniqueResult();

iBATIS 스타일(네임드 쿼리)
iBATIS 처럼 쿼리를 매핑 파일로 분리할 수 있습니다.
<hibernate-mapping>
    <query name="getArticle">
    <![CDATA[
        from Article where id = :id
    ]]>
    </query>
</hibernate-mapping>

분리된 쿼리는 getNamedQuery() 메서드를 통해 가져올 수 있습니다.
Query query = session.getNamedQuery("getArticle");

신고

'Hibernate' 카테고리의 다른 글

HQL - where 절  (0) 2008.04.13
HQL - 시작, from 절  (0) 2008.04.13
HQL - API  (0) 2008.04.13
늦은로딩과 조회방식  (0) 2008.04.09
동시 접근 제어  (0) 2008.03.29
openSession()과 currentSession()의 close()  (0) 2008.03.04
Posted by 째코


티스토리 툴바