Hibernateは現在、直感的で拡張可能なcriteriaクエリAPIを用意しています。今ではこのAPIは、成熟したHQLクエリの機能に比べて力不足です。特にcriteriaクエリは射影や集約をサポートしていません。
net.sf.hibernate.Criteriaインタフェースは特定の永続性クラスに対するクエリを表現しています。SessionはCriteriaインスタンスのファクトリです。
Criteria crit = sess.createCriteria(Cat.class); crit.setMaxResults(50); List cats = crit.list();
個別のクエリ・クライテリオン(問い合わせの判定基準)はインターフェイスnet.sf.hibernate.expression.Criterionのインスタンスです。net.sf.hibernate.expression.Expressionクラスはある組み込みのCriterion型を取得するためのファクトリメソッドを定義します。
List cats = sess.createCriteria(Cat.class) .add( Expression.like("name", "Fritz%") ) .add( Expression.between("weight", minWeight, maxWeight) ) .list();
Expressionは論理的にグループ化されます。
List cats = sess.createCriteria(Cat.class) .add( Expression.like("name", "Fritz%") ) .add( Expression.or( Expression.eq( "age", new Integer(0) ), Expression.isNull("age") ) ) .list();
List cats = sess.createCriteria(Cat.class) .add( Expression.in( "name", new String[] { "Fritz", "Izi", "Pk" } ) ) .add( Expression.disjunction() .add( Expression.isNull("age") ) .add( Expression.eq("age", new Integer(0) ) ) .add( Expression.eq("age", new Integer(1) ) ) .add( Expression.eq("age", new Integer(2) ) ) ) ) .list();
元々あるcriterion型(Expressionのサブクラス)はかなりの範囲に及びますが、特に有用なのはSQLを直接指定できるものです。
List cats = sess.createCriteria(Cat.class) .add( Expression.sql("lower({alias}.name) like lower(?)", "Fritz%", Hibernate.STRING) ) .list();
プレースホルダ{alias}は、問い合わせを受けたエンティティの行の別名によって置き換えられます。
net.sf.hibernate.expression.Orderを使って結果を整列することができます。
List cats = sess.createCriteria(Cat.class) .add( Expression.like("name", "F%") .addOrder( Order.asc("name") ) .addOrder( Order.desc("age") ) .setMaxResults(50) .list();
createCriteria()を使い関連をナビゲートすることで、容易に関係するエンティティに制約を指定できます。
List cats = sess.createCriteria(Cat.class) .add( Expression.like("name", "F%") .createCriteria("kittens") .add( Expression.like("name", "F%") .list();
2番目のcreateCriteria()は、kittensコレクションの要素を参照する新しいCriteriaインスタンスを返すことに注意してください。
以下のような方法も、状況により有用です。
List cats = sess.createCriteria(Cat.class) .createAlias("kittens", "kt") .createAlias("mate", "mt") .add( Expression.eqProperty("kt.name", "mt.name") ) .list();
(ここでcreateAlias())は新しいCriteriaインスタンスを作成しません。)
前の2つのクエリによって返されるCatインスタンスによって保持されるkittensコレクションは、criteriaによって事前にフィルタリングされないことに注意してください。もしcriteriaと対応するkittenを取得したいなら、returnMaps()を使わなければなりません。
List cats = sess.createCriteria(Cat.class) .createCriteria("kittens", "kt") .add( Expression.eq("name", "F%") ) .returnMaps() .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"); }
setFetchMode()を使い、実行時に関連の復元方法を指定することができます。
List cats = sess.createCriteria(Cat.class) .add( Expression.like("name", "Fritz%") ) .setFetchMode("mate", FetchMode.EAGER) .setFetchMode("kittens", FetchMode.EAGER) .list();
このクエリはアウター・ジョインでmate と kittensの両方をフェッチします。
net.sf.hibernate.expression.Exampleクラスを使って、与えられたインスタンスから クエリ・クライテリオンを構築することができます。
Cat cat = new Cat(); cat.setSex('F'); cat.setColor(Color.BLACK); List results = session.createCriteria(Cat.class) .add( Example.create(cat) ) .list();
バージョン・プロパティ、識別子、関連は無視されます。デフォルトではnull値のプロパティは除外されます。
どのようにExampleを適用するか、状況に応じて調整することができます。
Example example = Example.create(cat) .excludeZeroes() //ゼロ値プロパティを除外します .excludeProperty("color") //"color"という名前のプロパティを除外します .ignoreCase() //大文字・小文字の違いを無視して文字列の比較を行います .enableLike(); //文字列の比較にlikeを使用します List results = session.createCriteria(Cat.class) .add(example) .list();
関連オブジェクトにcriteriaを指定するExampleを使うことも可能です。
List results = session.createCriteria(Cat.class) .add( Example.create(cat) ) .createCriteria("mate") .add( Example.create( cat.getMate() ) ) .list();