Hibernate - Criteria Sample Code

    1. Hibernate中Criteria的完整用法 
    2. 最近在项目中使用 Spring 和 Hibernate 进行开发,有感于 Criteria 比较好用,在查询方法
    3. 
    4. 设计上可以灵活的根据 Criteria 的特点来方便地进行查询条件的组装。现在对 Hibernate的Criteria 的用法进行总结:
    5.    Hibernate 设计了 CriteriaSpecification 作为 Criteria 的父接口,下面提供了 Criteria和DetachedCriteria 。 
    6.    Criteria 和 DetachedCriteria 的主要区别在于创建的形式不一样, Criteria 是在线的,所
    7. 以它是由 Hibernate Session 进行创建的;而 DetachedCriteria 是离线的,创建时无需 
    8. Session,DetachedCriteria 提供了 2 个静态方法 forClass(Class) 或 forEntityName(Name) 
    9. 进行DetachedCriteria 实例的创建。 Spring 的框架提供了getHibernateTemplate
    10. ().findByCriteria(detachedCriteria) 方法可以很方便地根据DetachedCriteria 来返回查询结
    11. 果。 
    12.    Criteria 和 DetachedCriteria 均可使用 Criterion 和 Projection 设置查询条件。可以设
    13. 置 FetchMode( 联合查询抓取的模式 ) ,设置排序方式。对于 Criteria 还可以设置 FlushModel 
    14. (冲刷 Session 的方式)和 LockMode (数据库锁模式)。 
    15. 下面对 Criterion 和 Projection 进行详细说明。
    16.      Criterion 是 Criteria 的查询条件。Criteria 提供了 add(Criterion criterion) 方法来
    17. 添加查询条件。
    18.      Criterion 接口的主要实现包括: Example 、 Junction 和 SimpleExpression 。而 
    19. Junction 的实际使用是它的两个子类 conjunction 和 disjunction ,分别是使用 AND 和 OR 操
    20. 作符进行来联结查询条件集合。
    21.      Criterion 的实例可以通过 Restrictions 工具类来创建,Restrictions 提供了大量的静态
    22. 方法,如 eq (等于)、 ge (大于等于)、 between 等来方法的创建 Criterion 查询条件 
    23. (SimpleExpression 实例)。除此之外, Restrictions 还提供了方法来创建 conjunction 和 
    24. disjunction 实例,通过往该实例的 add(Criteria) 方法来增加查询条件形成一个查询条件集合
    25.      至于 Example 的创建有所不同, Example 本身提供了一个静态方法 create(Object 
    26. entity) ,即根据一个对象(实际使用中一般是映射到数据库的对象)来创建。然后可以设置一些
    27. 过滤条件: 
    28. Example exampleUser =Example.create(u) 
    29. .ignoreCase() // 忽略大小写 
    30. .enableLike(MatchMode.ANYWHERE); 
    31. // 对 String 类型的属性,无论在那里值在那里都匹配。相当于 %value% 
    32.   Project 主要是让 Criteria 能够进行报表查询,并可以实现分组。 Project 主要有 
    33. SimpleProjection 、 ProjectionList 和 Property 三个实现。其中 SimpleProjection 和 
    34. ProjectionList 的实例化是由内建的 Projections 来完成,如提供的 avg 、 count 、 max 、 
    35. min 、 sum 可以让开发者很容易对某个字段进行统计查询。 
    36.        Property 是对某个字段进行查询条件的设置,如通过Porperty.forName(“color”).in
    37. (new String[]{“black”,”red”,”write”}); 则可以创建一个 Project 实例。通过 
    38. criteria 的 add(Project) 方法加入到查询条件中去。 
    39.     使用 Criteria 进行查询,主要要清晰的是 Hibernate 提供了那些类和方法来满足开发中查
    40. 询条件的创建和组装,下面介绍几种用法:
    41. 1. 创建一个Criteria 实例
    42. org.hibernate.Criteria接口表示特定持久类的一个查询。Session是 Criteria实例的工厂。
    43. Criteria crit = sess.createCriteria(Cat.class);
    44. crit.setMaxResults(50);
    45. List cats = crit.list();
    46. 2. 限制结果集内容
    47. 一个单独的查询条件是org.hibernate.criterion.Criterion 接口的一个实例。
    48. org.hibernate.criterion.Restrictions类 定义了获得某些内置Criterion类型的工厂方法。
    49. List cats = sess.createCriteria(Cat.class)
    50.     .add( Restrictions.like("name", "Fritz%") )
    51.     .add( Restrictions.between("weight", minWeight, maxWeight) )
    52.     .list();
    53. 约束可以按逻辑分组。 
    54. List cats = sess.createCriteria(Cat.class)
    55.     .add( Restrictions.like("name", "Fritz%") )
    56.     .add( Restrictions.or(
    57.         Restrictions.eq( "age", new Integer(0) ),
    58.         Restrictions.isNull("age")
    59.     ) )
    60.     .list();
    61. List cats = sess.createCriteria(Cat.class)
    62.     .add( Restrictions.in( "name", new String[] { "Fritz", "Izi", "Pk" } ) )
    63.     .add( Restrictions.disjunction()
    64.         .add( Restrictions.isNull("age") )
    65.         .add( Restrictions.eq("age", new Integer(0) ) )
    66.         .add( Restrictions.eq("age", new Integer(1) ) )
    67.         .add( Restrictions.eq("age", new Integer(2) ) )
    68.     ) )
    69.     .list();
    70. Hibernate提供了相当多的内置criterion类型(Restrictions 子类), 但是尤其有用的是可以允许
    71. 你直接使用SQL。
    72. List cats = sess.createCriteria(Cat.class)
    73.     .add( Restrictions.sql("lower({alias}.name) like lower(?)", "Fritz%", 
    74. Hibernate.STRING) )
    75.     .list();
    76. {alias}占位符应当被替换为被查询实体的列别名。 
    77. Property实例是获得一个条件的另外一种途径。你可以通过调用Property.forName() 创建一个
    78. Property。 
    79.   Property age = Property.forName("age");
    80. List cats = sess.createCriteria(Cat.class)
    81.     .add( Restrictions.disjunction()
    82.         .add( age.isNull() )
    83.         .add( age.eq( new Integer(0) ) )
    84.         .add( age.eq( new Integer(1) ) )
    85.         .add( age.eq( new Integer(2) ) )
    86.     ) )
    87.     .add( Property.forName("name").in( new String[] { "Fritz", "Izi", "Pk" } ) )
    88.     .list();
    89. 3. 结果集排序
    90. 你可以使用org.hibernate.criterion.Order来为查询结果排序。 
    91. List cats = sess.createCriteria(Cat.class)
    92.     .add( Restrictions.like("name", "F%")
    93.     .addOrder( Order.asc("name") )
    94.     .addOrder( Order.desc("age") )
    95.     .setMaxResults(50)
    96.     .list();
    97. List cats = sess.createCriteria(Cat.class)
    98.     .add( Property.forName("name").like("F%") )
    99.     .addOrder( Property.forName("name").asc() )
    100.     .addOrder( Property.forName("age").desc() )
    101.     .setMaxResults(50)
    102.     .list();
    103. 4. 关联
    104. 你可以使用createCriteria()非常容易的在互相关联的实体间建立 约束。
    105. List cats = sess.createCriteria(Cat.class)
    106.     .add( Restrictions.like("name", "F%")
    107.     .createCriteria("kittens")
    108.         .add( Restrictions.like("name", "F%")
    109.     .list();
    110. 注意第二个 createCriteria()返回一个新的 Criteria实例,该实例引用kittens 集合中的元素。 
    111. 接下来,替换形态在某些情况下也是很有用的。
    112. List cats = sess.createCriteria(Cat.class)
    113.     .createAlias("kittens", "kt")
    114.     .createAlias("mate", "mt")
    115.     .add( Restrictions.eqProperty("kt.name", "mt.name") )
    116.     .list();
    117. (createAlias()并不创建一个新的 Criteria实例。) 
    118. Cat实例所保存的之前两次查询所返回的kittens集合是 没有被条件预过滤的。如果你希望只获得
    119. 符合条件的kittens, 你必须使用returnMaps()。 
    120. List cats = sess.createCriteria(Cat.class)
    121.     .createCriteria("kittens", "kt")
    122.     .add( Restrictions.eq("name", "F%") )
    123.     .returnMaps()
    124.     .list();
    125. Iterator iter = cats.iterator();
    126. while ( iter.hasNext() ) {
    127.     Map map = (Map) iter.next();
    128.     Cat cat = (Cat) map.get(Criteria.ROOT_ALIAS);
    129.     Cat kitten = (Cat) map.get("kt");
    130. }
    131. 5. 动态关联抓取
    132. 你可以使用setFetchMode()在运行时定义动态关联抓取的语义。 
    133. List cats = sess.createCriteria(Cat.class)
    134.     .add( Restrictions.like("name", "Fritz%") )
    135.     .setFetchMode("mate", FetchMode.EAGER)
    136.     .setFetchMode("kittens", FetchMode.EAGER)
    137.     .list();
    138. 这个查询可以通过外连接抓取mate和kittens。
    139. 6. 查询示例
    140. org.hibernate.criterion.Example类允许你通过一个给定实例 构建一个条件查询。
    141. Cat cat = new Cat();
    142. cat.setSex('F');
    143. cat.setColor(Color.BLACK);
    144. List results = session.createCriteria(Cat.class)
    145.     .add( Example.create(cat) )
    146.     .list();
    147. 版本属性、标识符和关联被忽略。默认情况下值为null的属性将被排除。 
    148. 可以自行调整Example使之更实用。 
    149. Example example = Example.create(cat)
    150.     .excludeZeroes()           //exclude zero valued properties
    151.     .excludeProperty("color")  //exclude the property named "color"
    152.     .ignoreCase()              //perform case insensitive string comparisons
    153.     .enableLike();             //use like for string comparisons
    154. List results = session.createCriteria(Cat.class)
    155.     .add(example)
    156.     .list();
    157. 甚至可以使用examples在关联对象上放置条件。
    158. List results = session.createCriteria(Cat.class)
    159.     .add( Example.create(cat) )
    160.     .createCriteria("mate")
    161.         .add( Example.create( cat.getMate() ) )
    162.     .list();
    163. 7. 投影(Projections)、聚合(aggregation)和分组(grouping)
    164. org.hibernate.criterion.Projections是 Projection 的实例工厂。我们通过调用 
    165. setProjection()应用投影到一个查询。 
    166. List results = session.createCriteria(Cat.class)
    167.     .setProjection( Projections.rowCount() )
    168.     .add( Restrictions.eq("color", Color.BLACK) )
    169.     .list();
    170. List results = session.createCriteria(Cat.class)
    171.     .setProjection( Projections.projectionList()
    172.         .add( Projections.rowCount() )
    173.         .add( Projections.avg("weight") )
    174.         .add( Projections.max("weight") )
    175.         .add( Projections.groupProperty("color") )
    176.     )
    177.     .list();
    178.  
    179. 在一个条件查询中没有必要显式的使用 "group by" 。某些投影类型就是被定义为 分组投影,他
    180. 们也出现在SQL的group by子句中。 
    181. 可以选择把一个别名指派给一个投影,这样可以使投影值被约束或排序所引用。下面是两种不同的
    182. 实现方式:
    183. List results = session.createCriteria(Cat.class)
    184.     .setProjection( Projections.alias( Projections.groupProperty("color"), "colr" ) )
    185.     .addOrder( Order.asc("colr") )
    186.     .list();
    187.  
    188. List results = session.createCriteria(Cat.class)
    189.     .setProjection( Projections.groupProperty("color").as("colr") )
    190.     .addOrder( Order.asc("colr") )
    191.     .list();
    192. alias()和as()方法简便的将一个投影实例包装到另外一个 别名的Projection实例中。简而言之,
    193. 当你添加一个投影到一个投影列表中时 你可以为它指定一个别名: 
    194. List results = session.createCriteria(Cat.class)
    195.     .setProjection( Projections.projectionList()
    196.         .add( Projections.rowCount(), "catCountByColor" )
    197.         .add( Projections.avg("weight"), "avgWeight" )
    198.         .add( Projections.max("weight"), "maxWeight" )
    199.         .add( Projections.groupProperty("color"), "color" )
    200.     )
    201.     .addOrder( Order.desc("catCountByColor") )
    202.     .addOrder( Order.desc("avgWeight") )
    203.     .list();
    204. List results = session.createCriteria(Domestic.class, "cat")
    205.     .createAlias("kittens", "kit")
    206.     .setProjection( Projections.projectionList()
    207.         .add( Projections.property("cat.name"), "catName" )
    208.         .add( Projections.property("kit.name"), "kitName" )
    209.     )
    210.     .addOrder( Order.asc("catName") )
    211.     .addOrder( Order.asc("kitName") )
    212.     .list();
    213. 也可以使用Property.forName()来表示投影:
    214. List results = session.createCriteria(Cat.class)
    215.     .setProjection( Property.forName("name") )
    216.     .add( Property.forName("color").eq(Color.BLACK) )
    217.     .list();
    218. List results = session.createCriteria(Cat.class)
    219.     .setProjection( Projections.projectionList()
    220.         .add( Projections.rowCount().as("catCountByColor") )
    221.         .add( Property.forName("weight").avg().as("avgWeight") )
    222.         .add( Property.forName("weight").max().as("maxWeight") )
    223.         .add( Property.forName("color").group().as("color" )
    224.     )
    225.     .addOrder( Order.desc("catCountByColor") )
    226.     .addOrder( Order.desc("avgWeight") )
    227.     .list();
    228. 8. 离线(detached)查询和子查询
    229. DetachedCriteria类使你在一个session范围之外创建一个查询,并且可以使用任意的 Session来
    230. 执行它。
    231. DetachedCriteria query = DetachedCriteria.forClass(Cat.class)
    232.     .add( Property.forName("sex").eq('F') );
    233. //创建一个Session
    234. Session session = .;
    235. Transaction txn = session.beginTransaction();
    236. List results = query.getExecutableCriteria(session).setMaxResults(100).list();
    237. txn.commit();
    238. session.close();
    239. DetachedCriteria也可以用以表示子查询。条件实例包含子查询可以通过 Subqueries或者
    240. Property获得。
    241. DetachedCriteria avgWeight = DetachedCriteria.forClass(Cat.class)
    242.     .setProjection( Property.forName("weight").avg() );
    243. session.createCriteria(Cat.class)
    244.     .add( Property.forName("weight).gt(avgWeight) )
    245.     .list();
    246. DetachedCriteria weights = DetachedCriteria.forClass(Cat.class)
    247.     .setProjection( Property.forName("weight") );
    248. session.createCriteria(Cat.class)
    249.     .add( Subqueries.geAll("weight", weights) )
    250.     .list();
    251. 相互关联的子查询也是有可能的:
    252. DetachedCriteria avgWeightForSex = DetachedCriteria.forClass(Cat.class, "cat2")
    253.     .setProjection( Property.forName("weight").avg() )
    254.     .add( Property.forName("cat2.sex").eqProperty("cat.sex") );
    255. session.createCriteria(Cat.class, "cat")
    256.     .add( Property.forName("weight).gt(avgWeightForSex) )
    257.     .list();
    要對資料庫管理系統進行操作,最基本的就是使用SQL(Standard Query Language)語句,大部份的資料庫都支援標準的SQL語句,然而也有一些特定於資料庫的SQL語句,應用程式配合SQL語句進行資料庫查詢時,若使用到特定於資料庫的SQL語句,程式本身會有相依於特定資料庫的問題。 
  1. 使用Hibernate時,即使您不了解SQL的使用與撰寫,也可以使用它所提供的API來進行SQL語句查詢,org.hibernate.Criteria對SQL進行封裝,您可以從Java物件的觀點來組合各種查詢條件,由Hibernate自動為您產生SQL語句,而不用特別管理SQL與資料庫相依的問題。 
  2. 以最基本的查詢來說,如果您想要查詢某個物件所對應的資料表中所有的內容,您可以如下進行查詢: 
  3. Criteria criteria = session.createCriteria(User.class); 
  4. List users = criteria.list(); 
  5.     
  6. for(Iterator it = users.iterator(); it.hasNext(); ) { 
  7.     User user = (User) it.next(); 
  8.     System.out.println(user.getId() + 
  9.                              " /t " + user.getName() + 
  10.                           "/" + user.getAge());    
  11. Criteria建立後,若不給予任何的條件,預設是查詢物件所對應表格之所有資料,如果您執行以上的程式片段,並於設定檔中設定了了Hibernate的”show_sql”屬性,則可以在主控下看到以下的SQL語句之產生: 
  12. Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ 
  13. Criteria基本查詢條件設定 
  14. org.hibernate.Criteria實際上是個條件附加的容器,如果想要設定查詢條件,則要使用org.hibernate.criterion.Restrictions的各種靜態方法傳回org.hibernate.criterion.Criteria實例,傳回的每個org.hibernate.criterion.Criteria實例代表著一個條件,您要使用org.hibernate.Criteria的add()方法加入這些條件實例,例如查詢”age”大於20且小於40的資料: 
  15. Criteria criteria = session.createCriteria(User.class); 
  16. criteria.add(Restrictions.gt("age", new Integer(20))); 
  17. criteria.add(Restrictions.lt("age", new Integer(40))); 
  18. List users = criteria.list(); 
  19.     
  20. for(Iterator it = users.iterator(); it.hasNext(); ) { 
  21.     User user = (User) it.next(); 
  22.     System.out.println(user.getId() + 
  23.                               " /t " + user.getName() + 
  24.                              "/" + user.getAge());    
  25. Restrictions的gt()方法表示大於(great than)的條件,而lt表示小於(less than)的條件,執行以上程式片段,觀察所產生的SQL語句,將使用where與and子句產來完成SQL的條件查詢: 
  26. Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where this_.age>? and this_.age 
  27. 使用add()方法加入條件時,預設是使用and來組合條件,如果要用or的方式來組合條件,則可以使用Restrictions.or()方法,例如結合age等於(eq)20或(or)age為空(isNull)的條件: 
  28. Criteria criteria = session.createCriteria(User.class); 
  29. criteria.add(Restrictions.or( 
  30.                    Restrictions.eq("age", new Integer(20)), 
  31.                    Restrictions.isNull("age") 
  32.                )); 
  33. List users = criteria.list(); 
  34. 觀察所產生的SQL語句,將使用where與or子句完成SQL的條件查詢: 
  35. Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where (this_.age=? or this_.age is null) 
  36. 您也可以使用Restrictions.like()方法來進行SQL中like子句的功能,例如查詢”name”中名稱為”just”開頭的資料: 
  37. Criteria criteria = session.createCriteria(User.class); 
  38. criteria.add(Restrictions.like("name", "just%")); 
  39. List users = criteria.list(); 
  40. 觀察所產生的SQL語句如下: 
  41. Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where this_.name like ? 
  42. Restrictions的幾個常用限定查詢方法如下表所示: 
  43. 方法  說明  
  44. Restrictions.eq 等於 
  45. Restrictions.allEq 使用Map,使用key/value進行多個等於的比對 
  46. Restrictions.gt  大於 > 
  47. Restrictions.ge  大於等於 >
  48. Restrictions.lt  小於 < 
  49. Restrictions.le 小於等於 <
  50. Restrictions.between 對應SQL的BETWEEN子句 
  51. Restrictions.like 對應SQL的LIKE子句 
  52. Restrictions.in  對應SQL的in子句 
  53. Restrictions.and and關係 
  54. Restrictions.or or關係 
  55. Criteria進階查詢條件設定 
  56. 使用Criteria進行查詢時,不僅僅能組合出SQL中where子句的功能,還可以組合出如排序、統計、分組等的查詢功能。 
  57. 排序 
  58. 您可以使用Criteria進行查詢,並使用org.hibernate.criterion.Order對結果進行排序,例如使用Oder.asc(),指定根據”age”由小到大排序(反之則使用desc()): 
  59. Criteria criteria = session.createCriteria(User.class); 
  60. criteria.addOrder(Order.asc("age")); 
  61. List users = criteria.list(); 
  62. 注意在加入Order條件時,使用的是addOrder()方法,而不是add()方法,在產生SQL語句時,會使用order by與asc(desc)來進行排序指定: 
  63. Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ order by this_.age asc 
  64. 限定查詢筆數 
  65. Criteria的setMaxResults()方法可以限定查詢回來的筆數,如果配合setFirstResult()設定傳回查詢結果第一筆資料的位置,就可以實現簡單的分頁,例如傳回第51筆之後的50筆資料(如果有的話): 
  66. Criteria criteria = session.createCriteria(User.class); 
  67. criteria.setFirstResult(51); 
  68. criteria.setMaxResults(50); 
  69. List users = criteria.list(); 
  70. 根據您所指定得資料庫,Hibernate將自動產生與資料庫相依的限定筆數查詢子句,例如在MySQL中,將使用limit產生以下的SQL語句: 
  71. Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ limit ?, ? 
  72. 統計動作 
  73. 您可以對查詢結果進行統計動作,使用org.hibernate.criterion.Projections的avg()、rowCount()、count()、max()、min()、 countDistinct()等方法,再搭配Criteria的setProjection()方法加入條件設定,例如對查詢結果的"age"作平均: 
  74. Criteria criteria = session.createCriteria(User.class); 
  75. criteria.setProjection(Projections.avg("age")); 
  76. List users = criteria.list(); 
  77. 上面的程式將由Hibernate自動產生SQL的avg函數進行平均計算: 
  78. Hibernate: select avg(this_.age) as y0_ from T_USER this_ 
  79. 分組 
  80. 還可以配合Projections的groupProperty()來對結果進行分組,例如以"age"進行分組,也就是如果資料中"age"如果有 20、20、25、30,則以下會顯示20、25、30: 
  81. Criteria criteria = session.createCriteria(User.class); 
  82. criteria.setProjection(Projections.groupProperty("age")); 
  83. List users = criteria.list(); 
  84. 上面的程式將由Hibernate自動產生SQL的group by子句進行分組計算: 
  85. Hibernate: select this_.age as y0_ from T_USER this_ group by this_.age 
  86. 如果想同時結合統計與分組功能,則可以使用org.hibernate.criterion.ProjectionList,例如下面的程式會計算每個年齡各有多少個人: 
  87. ProjectionList projectionList = Projections.projectionList(); 
  88. projectionList.add(Projections.groupProperty("age")); 
  89. projectionList.add(Projections.rowCount()); 
  90. Criteria criteria = session.createCriteria(User.class); 
  91. criteria.setProjection(projectionList); 
  92. List users = criteria.list(); 
  93. 觀察所產生的SQL語句,將使用group by先進行分組,再針對每個分組進行count函數的計數 
  94. Hibernate: select this_.age as y0_, count(*) as y1_ from T_USER this_ group by this_.age 
  95. 根據已知物件進行查詢 
  96. 設定查詢條件並非一定要使用Restrictions,如果屬性條件很多,使用Restrictions也不方便,如果有一個已知的物件,則可以根據這個物件作為查詢的依據,看看是否有屬性與之類似的物件,例如: 
  97. User user = new User(); 
  98. user.setAge(new Integer(30)); 
  99. Criteria criteria = session.createCriteria(User.class); 
  100. criteria.add(Example.create(user)); 
  101. List users = criteria.list(); 
  102. 您可以透過org.hibernate.criterion.Example的create()方法來建立Example實例,Example實作了Criteria介面,因此可以使用add()方法加入至Criteria條件設定之中,Hibernate將自動過濾掉空屬性,根據已知物件上已設定的屬性,判定是否產生於where子句之中: 
  103. Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where (this_.age=?) 
  104. 設定SQL範本 
  105. 如果您了解如何撰寫SQL語句,想要設定一些Hibernate產生SQL時的範本,您也可以使用Restrictions的sqlRestriction()方法,提供SQL語法範本作限定查詢,例如查詢name以cater開頭的資料: 
  106. Criteria criteria = session.createCriteria(User.class); 
  107. criteria.add(Restrictions.sqlRestriction("{alias}.name LIKE (?)", "cater%", Hibernate.STRING)); 
  108. List users = criteria.list(); 
  109. 其中alias將被替換為與User類別相關的名稱,而?將被替換為cater%,也就是第二個參數所提供的值,sqlRestriction()方法第一個參數所設定的是where子句的部份,所以在SQL撰寫時,不必再寫where,觀察所產生的SQL語句,將使用您所設定的SQL範本作為基礎,來完成SQL的條件查詢: 
  110. Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where this_.name LIKE (?) 
  111. 如果有多個查詢條件,例如between子句的查詢,則可以如下: 
  112. Criteria criteria = session.createCriteria(User.class); 
  113. Integer[] ages = {new Integer(20), new Integer(40)}; 
  114. Type[] types = {Hibernate.INTEGER, Hibernate.INTEGER}; 
  115. criteria.add(Restrictions.sqlRestriction("{alias}.age BETWEEN (?) AND (?)", ages, types)); 
  116. List users = criteria.list(); 
  117. 觀察所產生的SQL語句如下: 
  118. Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where this_.age BETWEEN (?) AND (?) 
  119. 使用DetchedCriteria 
  120. Criteria與Session綁定,其生命週期跟隨著Session結束而結束,使用Criteria時進行查詢時,每次都要於執行時期動態建立物件,並加入各種查詢條件,隨著Session的回收,Criteria也跟著回收。 
  121. 為了能夠重複使用Criteria物件,在Hibernate 3中新增了org.hibernate.criterion.DetchedCriteria,您可以先建立DetchedCriteria實例,並加入各種查詢條件,並於需要查詢時再與Session綁定,獲得一個綁定Session的Criteria物件,例如: 
  122. // 先建立DetchedCriteria物件 
  123. DetachedCriteria detchedCriteria = DetachedCriteria.forClass(User.class); 
  124. // 加入查詢條件 
  125. detchedCriteria.add(Restrictions.ge("age",new Integer(25))); 
  126.        
  127. Session session = sessionFactory.openSession(); 
  128. // 綁定Session並返回一個Criteria實例 
  129. Criteria criteria = detchedCriteria.getExecutableCriteria(session); 
  130.        
  131. List users = criteria.list(); 
  132. 結論 
  133. Hibernate的Criteria API可以讓您使用物件的方式,組合出查詢資料庫系統的條件,Hibernate會自動依您所使用的資料庫,動態產生SQL語句,讓您的應用程式在存取資料庫時,不致於因撰寫了特定的SQL而相依於特定的資料庫,如果您的開發人員不熟悉SQL語句的撰寫,也可以試著使用Criteria來解決查詢資料庫的需求。 

 

  1. 1、创建一个Criteria实例
  2. net.sf.hibernate.Criteria这个接口代表对一个特定的持久化类的查询。Session是用来制造Criteria实例的工厂。 
  3. Criteria crit = sess.createCriteria(Cat.class);
  4. crit.setMaxResults(50);
  5. List cats = crit.list();
  6. 返回最多50条记录的结果集。
  7. 2、缩小结果集范围
  8. 一个查询条件(Criterion)是net.sf.hibernate.expression.Criterion接口的一个实例。类net.sf.hibernate.expression.Expression定义了获得一些内置的Criterion类型。 
  9. List cats = sess.createCriteria(Cat.class)
  10.     .add( Expression.like("name", "Fritz%") )
  11.     .add( Expression.between("weight", minWeight, maxWeight) )
  12.     .list();
  13. 表达式(Expressions)可以按照逻辑分组. 
  14. List cats = sess.createCriteria(Cat.class)
  15.     .add( Expression.like("name", "Fritz%") )
  16.     .add( Expression.or(
  17.      Expression.eq( "age", new Integer(0) ),
  18.      Expression.isNull("age")
  19.     ) )
  20.     .list();
  21. 返回(name like "Fritz%" and age 等于0 或者 age 为空)的结果集
  22. List cats = sess.createCriteria(Cat.class)
  23.     .add( Expression.in( "name", new String[] { "Fritz", "Izi", "Pk" } ) )
  24.     .add( Expression.disjunction()
  25.         .add( Expression.isNull("age") )
  26.      .add( Expression.eq("age", new Integer(0) ) )
  27.      .add( Expression.eq("age", new Integer(1) ) )
  28.      .add( Expression.eq("age", new Integer(2) ) )
  29.     ) )
  30.     .list();
  31. Expression.disjunction()----意思是可以按照逻辑分组
  32. 有很多预制的条件类型(Expression的子类)。有一个特别有用,可以让你直接嵌入SQL。 
  33. List cats = sess.createCriteria(Cat.class)
  34.     .add( Expression.sql("lower($alias.name) like lower(?)", "Fritz%", Hibernate.STRING) )
  35.     .list();
  36. 其中的{alias}是一个占位符,它将会被所查询实体的行别名所替代。(原文:The {alias} placeholder with be replaced by the row alias of the queried entity.) 
  37. 3、对结果排序
  38. 可以使用net.sf.hibernate.expression.Order对结果集排序. 
  39. List cats = sess.createCriteria(Cat.class)
  40.     .add( Expression.like("name", "F%")
  41.     .addOrder( Order.asc("name") )
  42.     .addOrder( Order.desc("age") )
  43.     .setMaxResults(50)
  44.     .list();
  45. 4、关联(Associations)
  46. 你可以在关联之间使用createCriteria(),很容易地在存在关系的实体之间指定约束。 
  47. List cats = sess.createCriteria(Cat.class)
  48.     .add( Expression.like("name", "F%")
  49.     .createCriteria("kittens")
  50.         .add( Expression.like("name", "F%")
  51.     .list();
  52. 注意,第二个createCriteria()返回一个Criteria的新实例,指向kittens集合类的元素。 
  53. 下面的替代形式在特定情况下有用。 
  54. List cats = sess.createCriteria(Cat.class)
  55.     .createAlias("kittens", "kt")
  56.     .createAlias("mate", "mt")
  57.     .add( Expression.eqProperty("kt.name", "mt.name") )
  58.     .list();
  59. (createAlias())并不会创建一个Criteria的新实例。) 
  60. 请注意,前面两个查询中Cat实例所持有的kittens集合类并没有通过criteria预先过滤!如果你希望只返回满足条件的kittens,你必须使用returnMaps()。 
  61. List cats = sess.createCriteria(Cat.class)
  62.     .createCriteria("kittens", "kt")
  63.         .add( Expression.eq("name", "F%") )
  64.     .returnMaps()
  65.     .list();
  66. Iterator iter = cats.iterator();
  67. while ( iter.hasNext() ) {
  68.     Map map = (Map) iter.next();
  69.     Cat cat = (Cat) map.get(Criteria.ROOT_ALIAS);
  70.     Cat kitten = (Cat) map.get("kt");
  71. }
  72. 5、动态关联对象获取(Dynamic association fetching)
  73. 可以在运行时通过setFetchMode()来改变关联对象自动获取的策略。 
  74. List cats = sess.createCriteria(Cat.class)
  75.     .add( Expression.like("name", "Fritz%") )
  76.     .setFetchMode("mate", FetchMode.EAGER)
  77.     .list();
  78. 这个查询会通过外连接(outer join)同时获得 mate和kittens。 
  79. 6、根据示例查询(Example queries)
  80. net.sf.hibernate.expression.Example类允许你从指定的实例创造查询条件。 
  81. Cat cat = new Cat();
  82. cat.setSex('F');
  83. cat.setColor(Color.BLACK);
  84. List results = session.createCriteria(Cat.class)
  85.     .add( Example.create(cat) )
  86.     .list();
  87. 版本属性,表示符属性和关联都会被忽略。默认情况下,null值的属性也被排除在外。 
  88. You can adjust how the Example is applied. 你可以调整示例(Example)如何应用。 
  89. Example example = Example.create(cat)
  90.     .excludeZeroes()           //exclude zero valued properties
  91.     .excludeProperty("color")  //exclude the property named "color"
  92.     .ignoreCase()              //perform case insensitive string comparisons
  93.     .enableLike();             //use like for string comparisons
  94. List results = session.createCriteria(Cat.class)
  95.     .add(example)
  96.     .list();
  97. 你甚至可以用示例对关联对象建立criteria。 
  98. List results = session.createCriteria(Cat.class)
  99.     .add( Example.create(cat) )
  100.     .createCriteria("mate")
  101.         .add( Example.create( cat.getMate() ) )
  102.     .list();

猜你喜欢

转载自blog.csdn.net/geggegeda/article/details/2972184