|
首先看DetachedCriteria這個類名,是由兩個單詞(detached和criteria)組成的,Criteria咱們知道是QBC查詢主要接口之一,它通過組裝各種Criterion對象來獲取實體,Hibernate中的Session是產(chǎn)生Criteria的工廠,Criterion實例一般來說都是通過Restrictions類獲取的,如下面這個例子: List cats = session.createCriteria(Cat.class) .add( Restrictions.like("name", "Iz%") ) .add( Restrictions.gt( "weight", new Float(minWeight) ) ) .addOrder( Order.asc("age") ) .list();
通過上述例子可以發(fā)現(xiàn)需要使用Session實例來獲取Criteria對象,再看另外一個單詞detached,意思為“分離的、分開的、分割的、未綁定依附的”意思,那到底跟誰分離、分開呢?對,就是session,也就是說兩個單詞合起來的意思是該類除了創(chuàng)建時不在依附于任何Session,但可以完整支持Criteria的功能,這就是DetachedCriteria的誕生的根本需求; 下面咱們再來討論下該類的應(yīng)用場景: 在常規(guī)的Web編程中,有大量的動態(tài)條件查詢,即用戶在網(wǎng)頁上面根據(jù)自身需要選擇錄入某些條件,程序根據(jù)用戶選擇內(nèi)容,動態(tài)生成查詢SQL語句,進行查詢。 針對這種需求,對于分層應(yīng)用程序來說,Web層需要傳遞一個包含了查詢的條件條件的列表給業(yè)務(wù)層對象(傳統(tǒng)上使用Map對象),業(yè)務(wù)層對象獲得這個條件列表之后,依次從列表取出條件,構(gòu)造查詢語句。這里的一個難點是條件列表用什么來構(gòu)造?那么這么做的缺陷就是Map對象可以傳遞的信息非常有限,只能傳遞name和value,無法傳遞究竟要做怎樣的條件運算,即這么name和value之間什么關(guān)系,是>,<,IN,AND,OR呢?這就要求業(yè)務(wù)層對象必須確切掌握每條entry的隱含條件。因此一旦隱含條件改變,業(yè)務(wù)層對象的查詢構(gòu)造算法必須相應(yīng)修改,但是這種查詢條件的改變是隱式約定的,而不是程序代碼約束的,因此非常容易出錯。DetachedCriteria的出現(xiàn)解決了上述問題; 下面介紹一下DetachedCriteria的日常使用; 1、DetachedCriteria類允許你在Hibernate的Session范圍外創(chuàng)建一個查詢,然后使用任意一個Session環(huán)境去執(zhí)行它,這種用法也是使用最多的用法,該類提供了如下兩個方法用以構(gòu)建DetachedCriteria對象
代碼如下: // 創(chuàng)建DetachedCriteria對象 DetachedCriteria query = DetachedCriteria.forClass(Cat.class).add( Property.forName("sex").eq('F') ); // 獲取Session對象 Session session = ....; // 開啟事務(wù) Transaction txn = session.beginTransaction(); // 將DetachedCriteria查詢對象與可執(zhí)行的Criteria實例關(guān)聯(lián)起來 List results = query.getExecutableCriteria(session).setMaxResults(100).list(); // 提交事務(wù) txn.commit(); // 關(guān)閉Session,釋放資源 session.close();
2、一個DetachedCriteria可用作子查詢,Criterion實例可以通過Subqueries和Property類調(diào)用DetachedCriteria構(gòu)建的子查詢,如下代碼所示: // 構(gòu)建所有Cat中的平均體重 DetachedCriteria avgWeight = DetachedCriteria.forClass(Cat.class) .setProjection(Property.forName("weight").avg()); // 獲取所有Cat中,高于平均提供的Cat的集合 session.createCriteria(Cat.class).add(Property.forName("weight").gt(avgWeight)) .list(); // 構(gòu)建所有Cat的提供集合列表 DetachedCriteria weights = DetachedCriteria.forClass(Cat.class) .setProjection(Property.forName("weight")); // 獲取所有Cat中,體重最大的Cat session.createCriteria(Cat.class).add(Subqueries.geAll("weight", weights)) .list(); }
關(guān)聯(lián)子查詢,即DetachedCriteria構(gòu)建的子查詢和Criteria構(gòu)建的查詢也可以直接交互,如下: 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();
最后在上一個當(dāng)用DetachedCriteria構(gòu)建的投影,有多個列的例子: DetachedCriteria sizeQuery = DetachedCriteria .forClass(SlEmployee.class).setProjection(Projections.projectionList() .add(Projections.property("userName")) .add(Projections.property("employeeName"))) .add(Restrictions.eq("userName", "CHENGYU")); List list = session.createCriteria(SlEmployee.class) .add(Subqueries.propertiesEq(new String[] { "userName", "employeeName" }, sizeQuery)).list();
實際項目中用的最多的是第一種用法,即用來構(gòu)建一個查詢對象,對于子查詢這種用法則用的較少,通過例子可以看出,子查詢的功能似乎才更能體現(xiàn)出DetachedCriteria的強大?。?/p>
轉(zhuǎn)自:https://blog.csdn.net/yu102655/article/details/52469180
|