mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-03-03 16:29:13 +00:00
git-svn-id: https://svn.jboss.org/repos/hibernate/trunk/Hibernate3/doc@8291 1b8cb986-b30d-0410-93ca-fae66ebed9b2
420 lines
18 KiB
XML
420 lines
18 KiB
XML
<chapter id="querycriteria">
|
|
<title>Criteria 질의들</title>
|
|
|
|
<para>
|
|
Hibernate는 직관적인, 확장 가능한 criteria query API를 특징 짓는다.
|
|
</para>
|
|
|
|
<sect1 id="querycriteria-creating">
|
|
<title><literal>Criteria</literal> 인스턴스 생성하기</title>
|
|
|
|
<para>
|
|
<literal>org.hibernate.Criteria</literal>인터페이스는 특정 영속 클래스에 대한 질의를 표현한다.
|
|
<literal>Session</literal>은 <literal>Criteria</literal> 인스턴스들에 대한 팩토리이다.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[Criteria crit = sess.createCriteria(Cat.class);
|
|
crit.setMaxResults(50);
|
|
List cats = crit.list();]]></programlisting>
|
|
|
|
</sect1>
|
|
|
|
<sect1 id="querycriteria-narrowing">
|
|
<title>결과 셋 제한하기</title>
|
|
|
|
<para>
|
|
개별적인 질의 기준은 <literal>org.hibernate.criterion.Criterion</literal> 인터페이스의 인스턴스이다.
|
|
<literal>org.hibernate.criterion.Restrictions</literal> 클래스는 어떤 미리 만들어진 <literal>Criterion</literal>
|
|
타입들을 얻는 팩토리 메소드들을 정의한다.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
|
|
.add( Restrictions.like("name", "Fritz%") )
|
|
.add( Restrictions.between("weight", minWeight, maxWeight) )
|
|
.list();]]></programlisting>
|
|
|
|
<para>
|
|
제한들은 논리적으로 그룹지워질 수도 있다.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
|
|
.add( Restrictions.like("name", "Fritz%") )
|
|
.add( Restrictions.or(
|
|
Restrictions.eq( "age", new Integer(0) ),
|
|
Restrictions.isNull("age")
|
|
) )
|
|
.list();]]></programlisting>
|
|
|
|
<programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
|
|
.add( Restrictions.in( "name", new String[] { "Fritz", "Izi", "Pk" } ) )
|
|
.add( Restrictions.disjunction()
|
|
.add( Restrictions.isNull("age") )
|
|
.add( Restrictions.eq("age", new Integer(0) ) )
|
|
.add( Restrictions.eq("age", new Integer(1) ) )
|
|
.add( Restrictions.eq("age", new Integer(2) ) )
|
|
) )
|
|
.list();]]></programlisting>
|
|
|
|
<para>
|
|
미리 만들어진 criterion 타입들(<literal>Restrictions</literal> 서브클래스들)의 영역이 꽤 존재하지만, 특히 유용한 것은
|
|
당신으로 하여금 SQL을 직접 지정하도록 해준다.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
|
|
.add( Restrictions.sql("lower({alias}.name) like lower(?)", "Fritz%", Hibernate.STRING) )
|
|
.list();]]></programlisting>
|
|
|
|
<para>
|
|
질의된 엔티티의 행 alias에 의해 대체된 <literal>{alias}</literal> placeholder.
|
|
</para>
|
|
|
|
<para>
|
|
criterion을 얻는 대안적인 접근법은 <literal>Property</literal> 인스턴스로부터 그것을 얻는 것이다. 당신은
|
|
<literal>Property.forName()</literal>을 호출하여 <literal>Property</literal>를 생성시킬 수 있다.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[
|
|
Property age = Property.forName("age");
|
|
List cats = sess.createCriteria(Cat.class)
|
|
.add( Restrictions.disjunction()
|
|
.add( age.isNull() )
|
|
.add( age.eq( new Integer(0) ) )
|
|
.add( age.eq( new Integer(1) ) )
|
|
.add( age.eq( new Integer(2) ) )
|
|
) )
|
|
.add( Property.forName("name").in( new String[] { "Fritz", "Izi", "Pk" } ) )
|
|
.list();]]></programlisting>
|
|
|
|
</sect1>
|
|
|
|
<sect1 id="querycriteria-ordering">
|
|
<title>결과들을 순서지우기(ordering)</title>
|
|
|
|
<para>
|
|
당신은 <literal>org.hibernate.criterion.Order</literal>를 사용하여 결과들을 순서(ordering)지울 수 있다.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
|
|
.add( Restrictions.like("name", "F%")
|
|
.addOrder( Order.asc("name") )
|
|
.addOrder( Order.desc("age") )
|
|
.setMaxResults(50)
|
|
.list();]]></programlisting>
|
|
|
|
<programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
|
|
.add( Property.forName("name").like("F%") )
|
|
.addOrder( Property.forName("name").asc() )
|
|
.addOrder( Property.forName("age").desc() )
|
|
.setMaxResults(50)
|
|
.list();]]></programlisting>
|
|
|
|
</sect1>
|
|
|
|
<sect1 id="querycriteria-associations" revision="2">
|
|
<title>연관들</title>
|
|
|
|
<para>
|
|
당신은 <literal>createCriteria()</literal>를 사용하여 연관들을 네비게이트함으로써 관계된 엔티티들에 대한 컨스트레인트들을
|
|
쉽게 지정할 수 있다.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
|
|
.add( Restrictions.like("name", "F%")
|
|
.createCriteria("kittens")
|
|
.add( Restrictions.like("name", "F%")
|
|
.list();]]></programlisting>
|
|
|
|
<para>
|
|
두 번째 <literal>createCriteria()</literal>는 <literal>Criteria</literal>의 새로운 인스턴스를 반환하며, 그것은
|
|
<literal>kittens</literal> 콜렉션의 요소들을 참조한다는 점을 노트하라.
|
|
</para>
|
|
|
|
<para>
|
|
다음 대체 형식은 어떤 환경들에서 유용하다.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
|
|
.createAlias("kittens", "kt")
|
|
.createAlias("mate", "mt")
|
|
.add( Restrictions.eqProperty("kt.name", "mt.name") )
|
|
.list();]]></programlisting>
|
|
|
|
<para>
|
|
(<literal>createAlias()</literal>는 <literal>Criteria</literal>의 새로운 인스턴스를 생성시키지 않는다.)
|
|
</para>
|
|
|
|
<para>
|
|
앞의 두 개의 질의들에 의해 반환된 <literal>Cat</literal> 인스턴스들에 의해 보관된 kittens 콜렉션들은 criteria에 의해
|
|
사전-필터링되지 <emphasis>않는다</emphasis>는 점을 노트하라! 만일 당신이 criteria(기준)과 일치하는 고양이 새끼들을
|
|
단지 검색하고자 원할 경우, 당신은 하나의 <literal>ResultTransformer</literal>를 사용해야 한다.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
|
|
.createCriteria("kittens", "kt")
|
|
.add( Restrictions.eq("name", "F%") )
|
|
.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP)
|
|
.list();
|
|
Iterator iter = cats.iterator();
|
|
while ( iter.hasNext() ) {
|
|
Map map = (Map) iter.next();
|
|
Cat cat = (Cat) map.get(Criteria.ROOT_ALIAS);
|
|
Cat kitten = (Cat) map.get("kt");
|
|
}]]></programlisting>
|
|
|
|
</sect1>
|
|
|
|
<sect1 id="querycriteria-dynamicfetching" revision="1">
|
|
<title>동적인 연관 페칭</title>
|
|
|
|
<para>
|
|
당신은 <literal>setFetchMode()</literal>를 사용하여 실행 시에 연관 페칭 의미를 지정할 수 있다.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
|
|
.add( Restrictions.like("name", "Fritz%") )
|
|
.setFetchMode("mate", FetchMode.EAGER)
|
|
.setFetchMode("kittens", FetchMode.EAGER)
|
|
.list();]]></programlisting>
|
|
|
|
<para>
|
|
이 질의는 outer 조인으로 <literal>mate</literal>와 <literal>kittens</literal> 모두를 페치할 것이다. 추가 정보는
|
|
<xref linkend="performance-fetching"/>을 보라.
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
<sect1 id="querycriteria-examples">
|
|
<title>예제 질의들</title>
|
|
|
|
<para>
|
|
<literal>org.hibernate.criterion.Example</literal> 클래스는 주어진 인스턴스로부터 질의 기준(criterion)을 구조화
|
|
시키는 것을 당신에게 허용해준다.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[Cat cat = new Cat();
|
|
cat.setSex('F');
|
|
cat.setColor(Color.BLACK);
|
|
List results = session.createCriteria(Cat.class)
|
|
.add( Example.create(cat) )
|
|
.list();]]></programlisting>
|
|
|
|
<para>
|
|
버전 프로퍼티들, 식별자들, 연관관계들이 무시된다. 디폴트로 null 값 프로퍼티들이 제외된다.
|
|
</para>
|
|
|
|
<para>
|
|
당신은 <literal>Example</literal>이 적용되는 방법을 조정할 수 있다.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[Example example = Example.create(cat)
|
|
.excludeZeroes() //exclude zero valued properties
|
|
.excludeProperty("color") //exclude the property named "color"
|
|
.ignoreCase() //perform case insensitive string comparisons
|
|
.enableLike(); //use like for string comparisons
|
|
List results = session.createCriteria(Cat.class)
|
|
.add(example)
|
|
.list();]]></programlisting>
|
|
|
|
<para>
|
|
당신은 연관된 객체들에 대한 criteria(기준)을 위치지우는데 examples를 사용할 수 있다.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[List results = session.createCriteria(Cat.class)
|
|
.add( Example.create(cat) )
|
|
.createCriteria("mate")
|
|
.add( Example.create( cat.getMate() ) )
|
|
.list();]]></programlisting>
|
|
|
|
</sect1>
|
|
|
|
<sect1 id="querycriteria-projection">
|
|
<title>Projections, aggregation 그리고 grouping</title>
|
|
<para>
|
|
<literal>org.hibernate.criterion.Projections</literal> 클래스는 <literal>Projection</literal> 인스턴스들에
|
|
대한 팩토리이다. 우리는 <literal>setProjection()</literal>을 호출하여 하나의 질의에 projection(투사,투영)을 적용시킨다.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[List results = session.createCriteria(Cat.class)
|
|
.setProjection( Projections.rowCount() )
|
|
.add( Restrictions.eq("color", Color.BLACK) )
|
|
.list();]]></programlisting>
|
|
|
|
<programlisting><![CDATA[List results = session.createCriteria(Cat.class)
|
|
.setProjection( Projections.projectionList()
|
|
.add( Projections.rowCount() )
|
|
.add( Projections.avg("weight") )
|
|
.add( Projections.max("weight") )
|
|
.add( Projections.groupProperty("color") )
|
|
)
|
|
.list();]]></programlisting>
|
|
|
|
<para>
|
|
criteria 질의 내에서는 명시적인 "group by"가 필수적이지 않다. 어떤 projection 타입들은
|
|
<emphasis>grouping projections</emphasis>들이게끔 정의되고, 그것은 또한 SQL <literal>group by</literal> 절 속에
|
|
나타난다.
|
|
</para>
|
|
|
|
<para>
|
|
alias는 선택적으로 projection에 할당될 수 있어서, 투사된(projected) 값은 제한(restriction)들 또는 ordering들 내에서
|
|
참조될 수 있다. 다음은 이것을 행하는 두 개의 다른 방법들이다:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[List results = session.createCriteria(Cat.class)
|
|
.setProjection( Projections.alias( Projections.groupProperty("color"), "colr" ) )
|
|
.addOrder( Order.asc("colr") )
|
|
.list();]]></programlisting>
|
|
|
|
<programlisting><![CDATA[List results = session.createCriteria(Cat.class)
|
|
.setProjection( Projections.groupProperty("color").as("colr") )
|
|
.addOrder( Order.asc("colr") )
|
|
.list();]]></programlisting>
|
|
|
|
<para>
|
|
<literal>alias()</literal> 메소드와 <literal>as()</literal> 메소드는 또 다른 alias 된
|
|
<literal>Projection</literal>의 인스턴스 내에 하나의 projection 인스턴스를 간단하게 포장한다. 지름길로서,
|
|
당신이 projection을 projection 리스트에 추가할 때 당신은 alias를 할당할 수 있다:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[List results = session.createCriteria(Cat.class)
|
|
.setProjection( Projections.projectionList()
|
|
.add( Projections.rowCount(), "catCountByColor" )
|
|
.add( Projections.avg("weight"), "avgWeight" )
|
|
.add( Projections.max("weight"), "maxWeight" )
|
|
.add( Projections.groupProperty("color"), "color" )
|
|
)
|
|
.addOrder( Order.desc("catCountByColor") )
|
|
.addOrder( Order.desc("avgWeight") )
|
|
.list();]]></programlisting>
|
|
|
|
<programlisting><![CDATA[List results = session.createCriteria(Domestic.class, "cat")
|
|
.createAlias("kittens", "kit")
|
|
.setProjection( Projections.projectionList()
|
|
.add( Projections.property("cat.name"), "catName" )
|
|
.add( Projections.property("kit.name"), "kitName" )
|
|
)
|
|
.addOrder( Order.asc("catName") )
|
|
.addOrder( Order.asc("kitName") )
|
|
.list();]]></programlisting>
|
|
|
|
<para>
|
|
당신은 또한 projection들을 표현하는데 <literal>Property.forName()</literal>을 사용할 수 있다:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[List results = session.createCriteria(Cat.class)
|
|
.setProjection( Property.forName("name") )
|
|
.add( Property.forName("color").eq(Color.BLACK) )
|
|
.list();]]></programlisting>
|
|
|
|
<programlisting><![CDATA[List results = session.createCriteria(Cat.class)
|
|
.setProjection( Projections.projectionList()
|
|
.add( Projections.rowCount().as("catCountByColor") )
|
|
.add( Property.forName("weight").avg().as("avgWeight") )
|
|
.add( Property.forName("weight").max().as("maxWeight") )
|
|
.add( Property.forName("color").group().as("color" )
|
|
)
|
|
.addOrder( Order.desc("catCountByColor") )
|
|
.addOrder( Order.desc("avgWeight") )
|
|
.list();]]></programlisting>
|
|
|
|
</sect1>
|
|
|
|
<sect1 id="querycriteria-detachedqueries">
|
|
<title>Detached 질의들과 서브질의들</title>
|
|
<para>
|
|
<literal>DetachedCriteria</literal> 클래스는 당신에게 세션 영역의 외부에서 질의를 생성시키도록 하고, 그런 다음 나중에
|
|
어떤 임의의 <literal>Session</literal>을 사용하여 그것을 실행하도록 한다.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[DetachedCriteria query = DetachedCriteria.forClass(Cat.class)
|
|
.add( Property.forName("sex").eq('F') );
|
|
|
|
Session session = ....;
|
|
Transaction txn = session.beginTransaction();
|
|
List results = query.getExecutableCriteria(session).setMaxResults(100).list();
|
|
txn.commit();
|
|
session.close();]]></programlisting>
|
|
|
|
<para>
|
|
<literal>DetachedCriteria</literal>는 또한 서브질의를 표현하는데 사용된다. 서브질의들을 포함하는 Criterion 인스턴스들은
|
|
<literal>Subqueries</literal> 또는 <literal>Property</literal>를 통해 얻어질 수 있다.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[DetachedCriteria avgWeight = DetachedCriteria.forClass(Cat.class)
|
|
.setProjection( Property.forName("weight").avg() );
|
|
session.createCriteria(Cat.class)
|
|
.add( Property.forName("weight).gt(avgWeight) )
|
|
.list();]]></programlisting>
|
|
|
|
<programlisting><![CDATA[DetachedCriteria weights = DetachedCriteria.forClass(Cat.class)
|
|
.setProjection( Property.forName("weight") );
|
|
session.createCriteria(Cat.class)
|
|
.add( Subqueries.geAll("weight", weights) )
|
|
.list();]]></programlisting>
|
|
|
|
<para>
|
|
심지어 상관관계 지워진 서브질의들이 가능하다:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[DetachedCriteria avgWeightForSex = DetachedCriteria.forClass(Cat.class, "cat2")
|
|
.setProjection( Property.forName("weight").avg() )
|
|
.add( Property.forName("cat2.sex").eqProperty("cat.sex") );
|
|
session.createCriteria(Cat.class, "cat")
|
|
.add( Property.forName("weight).gt(avgWeightForSex) )
|
|
.list();]]></programlisting>
|
|
|
|
</sect1>
|
|
|
|
|
|
<!--TODO: ResultSetTransformer + aliasing. AliasToBeanTransformer는 -JDO2에서 setResultClass와 유사한- 임의적인
|
|
사용자 객체들을 반환하는 것을 허용한다. ResultTransformer에 대한 일반적인 사용이 또한 설명될 수 있다. -->
|
|
|
|
<sect1 id="query-criteria-naturalid">
|
|
<title>natural 식별자에 의한 질의들</title>
|
|
|
|
<para>
|
|
대부분의 질의들에서, criteria 질의들을 포함하여, 질의 캐시는 매우 효율적이지 않다. 왜냐하면 질의 캐시 비유효성이
|
|
너무 자주 발생하기 때문이다. 하지만, 우리가 캐시 비유효성 알고리즘을 최적화 시킬 수 있는 한 가지 특별한 종류의 질의가
|
|
존재한다: 상수 natural 키에 의한 룩업. 몇몇 어플리케이션들에서, 이런 종류의 질의가 자주 발생한다. criteria API는
|
|
이 쓰임새를 위한 특별한 설비를 제공한다.
|
|
</para>
|
|
|
|
<para>
|
|
첫번째로 당신은 <literal><natural-id></literal>를 사용하여 당신의 엔티티에 대한 natural 키를 매핑
|
|
시켜야 하고, second-level 캐시 사용을 가능하게 해야 한다.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<class name="User">
|
|
<cache usage="read-write"/>
|
|
<id name="id">
|
|
<generator class="increment"/>
|
|
</id>
|
|
<natural-id>
|
|
<property name="name"/>
|
|
<property name="org"/>
|
|
</natural-id>
|
|
<property name="password"/>
|
|
</class>]]></programlisting>
|
|
|
|
<para>
|
|
이 기능은 <emphasis>가변성 있는</emphasis> natural 키들을 가진 엔티티들의 용도로 고안되어 있지 않음을 노트하라.
|
|
</para>
|
|
|
|
<para>
|
|
다음으로 , Hibernate 질의 캐시를 사용 가능하도록 하라.
|
|
</para>
|
|
|
|
<para>
|
|
이제 <literal>Restrictions.naturalId()</literal>는 캐시 알고리즘을 보다 효율적으로 사용할 수 있도록 우리에게 허용해준다.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[session.createCriteria(User.class)
|
|
.add( Restrictions.naturalId()
|
|
.set("name", "gavin")
|
|
.set("org", "hb")
|
|
).setCacheable(true)
|
|
.uniqueResult();]]></programlisting>
|
|
|
|
</sect1>
|
|
|
|
</chapter>
|