1.標准查詢簡介
3.分頁使用標准
4.排序結果
5.預測與聚合
9.投影(Projections)、聚合(aggregation)和分組(grouping)
1.標准查詢簡介(QBC:Query By Criteria)
Hibernate 提供了操縱對象和相應的 RDBMS 表中可用的數據的替代方法。一種方法是標准的 API,它允許你建立一個標准的可編程查詢對象來應用過濾規則和邏輯條件。
Hibernate Session 接口提供了 createCriteria() 方法,可用於創建一個 Criteria 對象,使當您的應用程序執行一個標准查詢時返回一個持久化對象的類的實例。
以下是一個最簡單的標准查詢的例子
Criteria cr = session.createCriteria(Employee.class); List results = cr.list();
QBC (Query By Criteria) 主要有Criteria,Criterion,Oder,Restrictions類組成
@Override public List<Role> getAllRoles() { // TODO Auto-generated method stub List<Role> roles = null; Session session =sessionFactory.getCurrentSession(); Criteria criteria = session.createCriteria(Role.class); Criterion criterion = Restrictions.eq("roleServer", "一夢十年"); criteria.add(criterion); roles = criteria.list(); return roles; }
= Restrictions.eq() 等於 <> Restrictions.not(Exprission.eq()) 不等於 > Restrictions.gt() 大於 >= Restrictions.ge() 大於等於 < Restrictions.lt() 小於 <= Restrictions.le() 小於等於 is null Restrictions.isnull() 等於空值 is not null Restrictions.isNotNull() 非空值 like Restrictions.like() 字符串模式匹配 and Restrictions.and() 邏輯與 and Restrictions.conjunction() 邏輯與 or Restrictions.or() 邏輯或 or Restrictions.disjunction() 邏輯或 not Restrictions.not() 邏輯非 in(列表) Restrictions.in() 等於列表中的某一個值 ont in(列表) Restrictions.not(Restrictions.in())不等於列表中任意一個值 between x and y Restrictions.between() 閉區間xy中的任意值 not between x and y Restrictions.not(Restrictions..between()) 小於值X或者大於值y
使用邏輯表達式創建 in 的條件組合
cri.add(Restrictions.in("chcStatus", new Object[]{"2","3","4"}));
使用邏輯表達式創建 AND 或 OR 的條件組合
@Override public List<Role> getAllRoles() { // TODO Auto-generated method stub List<Role> roles = null; Session session =sessionFactory.getCurrentSession(); Criteria criteria = session.createCriteria(Role.class); Criterion serverName = Restrictions.eq("roleServer", "一夢十年"); Criterion userOrder = Restrictions.eq("roleOrder", 1); LogicalExpression andExp = Restrictions.and(serverName, userOrder); criteria.add(andExp); return roles; }
你可以直接使用SQL。
List cats = sess.createCriteria(Cat.class) .add( Restrictions.sql("lower({alias}.name) like lower(?)", "Fritz%", Hibernate.STRING) ) .list();
{alias}占位符應當被替換為被查詢實體的列別名。
Property實例是獲得一個條件的另外一種途徑。你可以通過調用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();
3.分頁使用標准
這里有兩種分頁標准接口方法:
序號 | 方法描述 |
---|---|
1 | public Criteria setFirstResult(int firstResult),這種方法需要一個代表你的結果集的第一行的整數,以第 0 行為開始。 |
2 | public Criteria setMaxResults(int maxResults),這個方法設置了 Hibernate 檢索對象的 maxResults。 |
利用上述兩種方法結合在一起,我們可以在我們的 Web 或 Swing 應用程序構建一個分頁組件。以下是一個例子,利用它你可以一次取出 10 行:
Criteria cr = session.createCriteria(Employee.class); cr.setFirstResult(1); cr.setMaxResults(10); List results = cr.list();
4.排序結果
標准 API 提供了 org.hibernate.criterion.order 類可以去根據你的一個對象的屬性把你的排序結果集按升序或降序排列。這個例子演示了如何使用 Order 類對結果集進行排序:
Criteria cr = session.createCriteria(Employee.class); // To get records having salary more than 2000 cr.add(Restrictions.gt("salary", 2000)); // To sort records in descening order crit.addOrder(Order.desc("salary")); // To sort records in ascending order crit.addOrder(Order.asc("salary")); List results = cr.list();
5.預測與聚合
標准 API 提供了 org.hibernate.criterion.projections 類可得到各屬性值的平均值,最大值或最小值。Projections 類與 Restrictions 類相似,均提供了幾個獲取預測實例的靜態工廠方法。
以下是幾個例子,涵蓋了不同的情況,可按要求進行使用:
Criteria cr = session.createCriteria(Employee.class); // To get total row count. cr.setProjection(Projections.rowCount()); // To get average of a property. cr.setProjection(Projections.avg("salary")); // To get distinct count of a property. cr.setProjection(Projections.countDistinct("firstName")); // To get maximum of a property. cr.setProjection(Projections.max("salary")); // To get minimum of a property. cr.setProjection(Projections.min("salary")); // To get sum of a property. cr.setProjection(Projections.sum("salary"));
你可以使用createCriteria()非常容易的在互相關聯的實體間建立 約束。
List cats = sess.createCriteria(Cat.class) .add( Restrictions.like("name", "F%") .createCriteria("kittens") .add( Restrictions.like("name", "F%") .list();
注意第二個 createCriteria()返回一個新的 Criteria實例,該實例引用kittens 集合中的元素。
接下來,替換形態在某些情況下也是很有用的。
list cats = sess.createCriteria(Cat.class) .createAlias("kittens", "kt") .createAlias("mate", "mt") .add( Restrictions.eqProperty("kt.name", "mt.name") ) .list();
(createAlias()並不創建一個新的 Criteria實例。)
Cat實例所保存的之前兩次查詢所返回的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"); }
16.5. 動態關聯抓取
你可以使用setFetchMode()在運行時定義動態關聯抓取的語義。
List cats = sess.createCriteria(Cat.class)
.add( Restrictions.like("name", "Fritz%") )
.setFetchMode("mate", FetchMode.EAGER)
.setFetchMode("kittens", FetchMode.EAGER)
.list();
這個查詢可以通過外連接抓取mate和kittens。
org.hibernate.criterion.Example類允許你通過一個給定實例 構建一個條件查詢。
Role role = null; Session session = sessionFactory.getCurrentSession(); Role demoRole = new Role(); demoRole.setRoleSect("星宿"); Example example = Example.create(demoRole).excludeZeroes() ; Criteria criteria = session.createCriteria(Role.class); List<Role> roles =criteria.add(example).list();
注意:如何實體類中如果有int 或者doubole 類型的值而沒有設置值,一定要加 excludeZeroes() 條件
版本屬性、標識符和關聯被忽略。默認情況下值為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();
9.投影(Projections)、聚合(aggregation)和分組(grouping)

16.7. 投影(Projections)、聚合(aggregation)和分組(grouping) org.hibernate.criterion.Projections是 Projection 的實例工廠。我們通過調用 setProjection()應用投影到一個查詢。 List results = session.createCriteria(Cat.class) .setProjection( Projections.rowCount() ) .add( Restrictions.eq("color", Color.BLACK) ) .list(); 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(); 在一個條件查詢中沒有必要顯式的使用 "group by" 。某些投影類型就是被定義為 分組投影,他們也出現在SQL的group by子句中。 你可以選擇把一個別名指派給一個投影,這樣可以使投影值被約束或排序所引用。下面是兩種不同的實現方式: 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();
DetachedCriteria類使你在一個session范圍之外創建一個查詢,並且可以使用任意的 Session來執行它。
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();
Hibernate 設計了 CriteriaSpecification 作為 Criteria 的父接口,下面提供了 Criteria和DetachedCriteria 。
Criteria 和 DetachedCriteria 的主要區別在於創建的形式不一樣, Criteria 是在線的,所以它是由 Hibernate Session 進行創建的;而 DetachedCriteria 是離線的,
創建時無需 Session,DetachedCriteria 提供了 2 個靜態方法 forClass(Class) 或 forEntityName(Name)
進行DetachedCriteria 實例的創建。 Spring 的框架提供了getHibernateTemplate ().findByCriteria(detachedCriteria) 方法可以很方便地根據DetachedCriteria 來返回查詢結果。
Criteria 和 DetachedCriteria 均可使用 Criterion 和 Projection 設置查詢條件。可以設
置 FetchMode( 聯合查詢抓取的模式 ) ,設置排序方式。對於 Criteria 還可以設置 FlushModel
(沖刷 Session 的方式)和 LockMode (數據庫鎖模式)。