Hibernate温習(4)--三大類クエリーまとめ


Hibernateは現在、cretiria、hql、ローカルsqlの3つのクエリーに分けられています.
第一:cretiriaに関するクエリー
直感的で拡張性のある条件付きクエリーAPIはHibernateの特色です.15.1. Criteriaインスタンスorgを作成する.hibernate.Criteriaインタフェースは、特定の永続クラスのクエリーを表します.SessionはCriteriaインスタンスの工場です.
Criteria crit = sess.createCriteria(Cat.class);
crit.setMaxResults(50);
List cats = crit.list();

 15.2. 結果セットの内容を制限個別のクエリー条件はorgである.hibernate.criterion.Criterionインタフェースの一例.org.hibernate.criterion.Restrictionsクラスは、いくつかの組み込みCriterionタイプを取得するファクトリメソッドを定義します.
List cats = sess.createCriteria(Cat.class)
     .add( Restrictions.like("name", "Fritz%") )
     .add( Restrictions.between("weight", minWeight, maxWeight) )
     .list();

コンストレイントは論理的にグループ化できます.
List cats = sess.createCriteria(Cat.class)
     .add( Restrictions.like("name", "Fritz%") )
     .add( Restrictions.or(
         Restrictions.eq( "age", new Integer(0) ),
         Restrictions.isNull("age")
     ) )
     .list();
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();

Hibernateはかなりの組み込みcriterionタイプ(Restrictionsサブクラス)を提供していますが、特にSQLを直接使用できるようにするのに役立ちます.
 
List cats = sess.createCriteria(Cat.class)
     .add( Restrictions.sql("lower({alias}.name) like lower(?)", "Fritz%", Hibernate.STRING) )
     .list();

 
{alias}プレースホルダは、クエリーされたエンティティのカラム別名に置き換えられる必要があります.Propertyインスタンスは、1つの条件を得る別の方法です.Propertyを呼び出すことができますforName()Propertyを作成します.
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();

 15.3. 結果セットのソートorgを使用できます.hibernate.criterion.Orderはクエリの結果をソートします.
List cats = sess.createCriteria(Cat.class)
     .add( Restrictions.like("name", "F%")
     .addOrder( Order.asc("name") )
     .addOrder( Order.desc("age") )
     .setMaxResults(50)
     .list();
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();

 
15.4. 関連付けcreateCriteria()を使用すると、相互に関連するエンティティ間で制約を確立することができます.  
List cats = sess.createCriteria(Cat.class)
     .add( Restrictions.like("name", "F%")
     .createCriteria("kittens")
         .add( Restrictions.like("name", "F%")
     .list();

 
2番目のcreateCriteria()は、kittensセットの要素を参照する新しいCriteriaインスタンスを返すことに注意してください.次に,置換形態は場合によっては有用である.
List cats = sess.createCriteria(Cat.class)
     .createAlias("kittens", "kt")
     .createAlias("mate", "mt")
     .add( Restrictions.eqProperty("kt.name", "mt.name") )
     .list();

 
(createAlias()新しいCriteriaインスタンスは作成されません.)Catインスタンスが保存した前の2回のクエリから返されたkittensセットは、条件によって事前にフィルタされていません.条件を満たすkittensのみを取得したい場合は、returnMaps()を使用する必要があります.
List cats = sess.createCriteria(Cat.class)
     .createCriteria("kittens", "kt")
         .add( Restrictions.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");
}

 
15.5. 動的関連スナップsetFetchMode()を使用して、実行時に動的関連スナップの意味を定義できます.
List cats = sess.createCriteria(Cat.class)
     .add( Restrictions.like("name", "Fritz%") )
     .setFetchMode("mate", FetchMode.EAGER)
     .setFetchMode("kittens", FetchMode.EAGER)
     .list();

 
このクエリは、mateとkittensを外部接続でキャプチャできます.詳細については、19.1節「キャプチャポリシー(Fetching strategies)」を参照してください.15.6. クエリー例org.hibernate.criterion.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()            //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();

examplesを使用して、関連オブジェクトに条件を配置することもできます.
List results = session.createCriteria(Cat.class)
     .add( Example.create(cat) )
     .createCriteria("mate")
         .add( Example.create( cat.getMate() ) )
     .list();

 
15.7. 投影(Projections)、集約(aggregation)、グループ(grouping)org.hibernate.critterion.ProjectionsはProjectionのインスタンスファクトリです.setProjection()を呼び出してクエリーに投影を適用します.条件クエリーでgroupbyを明示的に使用する必要はありません.いくつかの投影タイプはパケット投影として定義され、SQLのgroupby句にも表示されます.投影に別名を割り当てることで、投影値をコンストレイントまたはソートして参照できます.次の2つの異なる実装方法を示します.
List results = session.createCriteria(Cat.class)
     .setProjection( Projections.alias( Projections.groupProperty("color"), "colr" ) )
     .addOrder( Order.asc("colr") )
     .list();
List results = session.createCriteria(Cat.class)
     .setProjection( Projections.groupProperty("color").as("colr") )
     .addOrder( Order.asc("colr") )
     .list();

 
alias()およびas()メソッドは、投影インスタンスを別の別名のProjectionインスタンスに簡単にパッケージします.簡単に言えば、投影リストに投影を追加すると、別名を指定できます.
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();
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();

Propertyも使えますforName()は、投影を表します.
List results = session.createCriteria(Cat.class)
     .setProjection( Property.forName("name") )
     .add( Property.forName("color").eq(Color.BLACK) )
     .list();
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();

 15.8. オフライン(detached)クエリーとサブクエリーDetachedCriteriaクラスでは、セッションの範囲外にクエリーを作成し、任意のセッションを使用して実行できます.
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();
DetachedCriteria          。              Subqueries  Property  。 

DetachedCriteria avgWeight = DetachedCriteria.forClass(Cat.class)
.setProjection( Property.forName("weight").avg() );
session.createCriteria(Cat.class)
.add( Property.forName("weight).gt(avgWeight) )
.list();
DetachedCriteria weights = DetachedCriteria.forClass(Cat.class)
.setProjection( Property.forName("weight") );
session.createCriteria(Cat.class)
.add( Subqueries.geAll("weight", weights) )
.list();

相互に関連付けられたサブクエリも可能です.
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();

 
 
第二:HQLクエリー
HQLではキーワードは大文字と小文字を区別しませんが、属性とクラス名は大文字と小文字を区別します.次に、様々なタイプのHibernateのHQLクエリーについて説明します.1、Hibernate HQLクエリ:単純属性クエリ
*単一属性クエリー、結果セット属性リストを返します.要素タイプとエンティティークラスの対応する属性タイプは一致しています.
*複数の属性クエリーで、返される集合要素はオブジェクト配列であり、配列要素のタイプと対応する属性がエンティティークラスのタイプと一致する配列の長さはselectの属性の個数に依存する*返される配列がオブジェクト化されていないと判断した場合は、HQLダイナミックインスタンス化Studioオブジェクトを使用できます.
2、Hibernate HQLクエリ:エンティティオブジェクトクエリ*N+1問題、デフォルトではqueryを使用する.iterateクエリーでは、N+1の問題が発生する可能性があります.いわゆるN+1はクエリー時にN+1のsql文を発行します.1:まずクエリー対象idリストのsqlを発行します.N:idリストからキャッシュにクエリーします.キャッシュに一致するデータが存在しない場合は、idに基づいて対応するsql文を発行します.
*listとiterateの違いは?*Listは毎回sql文を発行します.listはキャッシュにデータを入れます.キャッシュのデータを利用しません.*iterate:デフォルトではiterateはキャッシュデータを利用しますが、キャッシュにデータが存在しない場合はN+1の問題が発生します.
3、Hibernate HQLクエリー:条件クエリー*パラメータJavaコードをスペル文字列で渡すことができる:
List students = session.createQuery("select s.id, s.name from Student s where s.name like '%1%'").list();   

 
*採用可能?パラメータ(インデックス0から)Javaコードを渡します.
List students = session.createQuery("select s.id, s.name from Student s where s.name like ?").setParameter(0, "%1%").list();      //    ?            //      0        //      ,              //           

  
*パラメータ名を使用してパラメータを渡すことができます.
Javaコード:
 
List students = session.createQuery  ("select s.id, s.name from Student s where s.name like :myname").setParameter("myname", "%1%").list();    

 
*複数のパラメータを渡す場合は、setParamterListメソッドを使用できます.
Javaコード:
    
List students = session.createQuery("select s.id, s.name from Student s where s.id in(:myids)").setParameterList("myids", new Object[]{1, 2, 3, 4, 5}).list();

 
*HQLでは、データベースの関数を使用できます.たとえば、date_format
Javaコード:
List students = session.createQuery("select s.id, s.name from Student s where date_format(s.createTime, '%Y-%m')=?").setParameter(0, "2008-02").list();      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");                  //  2008-01-10 2008-02-15               List students = session.createQuery("select s.id, s.name from Student s where s.createTime between ? and ?")                .setParameter(0, sdf.parse("2008-01-10 00:00:00"))                .setParameter(1, sdf.parse("2008-02-15 23:59:59"))                      .list();     

 
4、Hibernate HQLクエリー:直接sqlを使ってクエリーを行う
Javaコード:
  
List students = session.createSQLQuery("select * from t_student").list();   

オブジェクトは返されませんが、すべてのプロパティです.  
5、Hibernate HQLクエリー:ページングクエリー
*setFirstResult()0から
*setMaxResults、各ページに表示されるデータ数
Javaコード:
List students = session.createQuery("from Student")                .setFirstResult(1)                .setMaxResults(2)                .list();    

 
6、Hibernate HQLクエリー:オブジェクトナビゲーションクエリー、HQLで採用する.ナビゲーション
7、Hibernate HQLクエリー:接続クエリー
*インライン
Sqlコード:
SELECT s.name, c.name FROM Student s (inner) join s.classes c    

 
*外部接続(左接続/右接続)Sqlコード:
SELECT s.name, c.name FROM Student s left join s.classes c   

  
 
 
8、Hibernate HQLクエリー:統計クエリー
Javaコード:
List students =session.createQuery("select c.name, count(s) from Student s join s.classes c " +"group by c.name order by c.name").list();      for (Iterator iter=students.iterator(); iter.hasNext();) {           Object[] obj = (Object[])iter.next();           System.out.println(obj[0] + ", " + obj[1]);      }  

 
9、DMLスタイルの操作(キャッシュと同期しないため、できるだけ少なく使う)
Javaコード:
session.createQuery  ("update Student s set s.name=? where s.id < ?")                           .setParameter(0, "  ")                           .setParameter(1, 5)                           .executeUpdate();    

 
キャッシュと同期していないため、上記の文を実行する前にstudentを1つのリストにカプセル化して取り出し、上記の文を実行してstudentのテーブルをデータ更新し、リストStudioテーブルを実行すると、このときのリストはテーブルから見つかったデータではなく、キャッシュから取ったデータ、つまり、Listはupdate前のデータを手に入れたので、このような同期が取れないので、このスタイルはできるだけ少なく使います.
この点からもHibernateは集約性,統計,大量の更新,削除などの操作には適していないことが分かる.
 
第三に、ローカルSQLクエリ
SQLQueryを使用するオリジナルSQLクエリに対する制御はSQLQueryインタフェースによって行われ、Sessionが実行する.createSQLQuery()はこのインタフェースを取得します.最も簡単な場合、以下の形式を採用することができます.
List cats  =  sess.createSQLQuery( " select * from cats " ).addEntity(Cat. class ).list(); 

 
このクエリは次のように指定されています.
SQLクエリー文字列
返されるエンティティの問合せ
ここで、結果セットのフィールド名は、マッピングファイルで指定されたフィールド名と同じと仮定される.複数のテーブルが接続されているクエリーでは、同じ名前のフィールドが複数のテーブルに表示される可能性があるため、問題が発生する可能性があります.次の方法では、フィールド名の重複を回避できます.
List cats  =  sess.createSQLQuery( " select {cat.*} from cats cat " ).addEntity( " cat " , Cat. class ).list(); 

 
このクエリは次のように指定されています.
SQLクエリ文は、Hibernateがフィールドの別名を使用できるプレースホルダ付きです.
返されたエンティティとそのSQLテーブルの別名をクエリーします.
addEntity()メソッドは、SQLテーブルの別名とエンティティクラスを関連付け、クエリー結果セットの形態を決定します.
addJoin()メソッドは、他のエンティティとセットの関連付けをロードするために使用することができる.
List cats  =  sess.createSQLQuery(
" select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id " )
.addEntity( " cat " , Cat. class )
.addJoin( " kitten " ,  " cat.kittens " )
.list(); 

 
元のSQLクエリは、単純なスカラー値またはスカラーとエンティティの結合体を返す可能性があります.
Double max  =  (Double) sess.createSQLQuery( " select max(cat.weight) as maxWeight from cats cat " )
.addScalar( " maxWeight " , Hibernate.DOUBLE);
.uniqueResult(); 

  
また、hbmファイルに結果セットマッピング情報を記述し、クエリーで使用することもできます.
List cats  =  sess.createSQLQuery(
" select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id " )
.setResultSetMapping( " catAndKitten " )
.list(); 

 
名前付きSQLクエリーは、マッピングドキュメントでクエリーの名前を定義し、名前付きHQLクエリーを呼び出すように名前付きSQLクエリーを直接呼び出すことができます.この場合、addEntity()メソッドを呼び出す必要はありません.
< sql - query name = " persons " > 
  < return  alias = " person "   class = " eg.Person " /> 
 Select person.NAME AS {person.name},person.AGE AS {person.age},person.SEX AS {person.sex} FROM PERSON person Where person.NAME LIKE :namePattern
</ sql - query > 

 
 
List people  =  sess.getNamedQuery( " persons " ).setString( " namePattern " , namePattern)
.setMaxResults( 50 )
.list();