Hibernate之DetachedCriteria、Criteria

xbynet發表於2017-04-21

問題九、Hibernate裡面如何用Criteria 查詢記錄數

【問題描述】在工作中,有一個比較複雜的feature使用的是hibernate的Criteria實現的查詢,但是PM要求在查詢資料前,先告知使用者有多少條資料,讓使用者去選擇返回多少條記錄。
【解決辦法】使用Projections.count(“property”) 或者 Projections.rowCount()

Criteria c = session.createCriteria(User.class);  
c.setProjection(Projections.rowCount());  
int rows=Integer.parseInt(c.uniqueResult().toString());
s.setProjection(null)  

參考:http://blog.csdn.net/virgoboy…

問題十、Hibernate Criteria Join with 3 Tables

Criteria c = session.createCriteria(Dokument.class, "dokument");
c.createAlias("dokument.role", "role"); // inner join by default
c.createAlias("role.contact", "contact");
c.add(Restrictions.eq("contact.lastName", "Test"));
return c.list();

或者這樣:

Criteria c = session.createCriteria(Dokument.class);
c.createAlias("role", "role"); // inner join by default
c.createAlias("role.contact", "contact");
c.add(Restrictions.eq("contact.lastName", "Test"));
return c.list();

如果實體物件中含有OneToMany關聯物件的情況,既是實體中含有list或Set等關聯實體集合的情況下怎麼辦呢?
這個還不知道怎麼辦,呵呵
方法其實是非常簡單的:

dc.createAlias("tags", "t");          
dc.add(Restrictions.eq("t.id", tagId));  

其中tags是個Set,但是想查詢屬性tags中含有id為tagId的實體,使用上面的就可以了。

這裡有一個特殊情況,如果是對引用物件的id查詢,則可以不用建立引用,也就是可以不呼叫createAlias()語句,如下所示:

DetachedCriteria dc = DetachedCriteria.forClass(Student.class);  
dc.add(Restrictions.like("team.id", teamId, MatchMode.ANYWHERE));  

據我個人的經驗,team後只能跟其主鍵屬性,比較其他屬性要用別名。

參考:http://stackoverflow.com/ques…
http://www.cnblogs.com/newpan…

問題十一、DetachedCriteria、Criteria 使用區別

在常規的Web程式設計中,有大量的動態條件查詢,即使用者在網頁上面自由選擇某些條件,程式根據使用者的選擇條件,動態生成SQL語句,進行查詢。
此時,我們不能在Web層使用Criteria,因為它是和Session繫結的。
DetachedCriteria可以解決這個問題,即在web層,程式設計師使用DetachedCriteria來構造查詢條件,然後將這個 DetachedCriteria作為方法呼叫引數傳遞給業務層物件。而業務層物件獲得DetachedCriteria之後,可以在session範圍內直接構造Criteria,進行查詢。就此,查詢語句的構造完全被搬離到web層實現,而業務層則只負責完成持久化和查詢的封裝即可,與查詢條件構造完全解耦,非常完美!

Criteria 和 DetachedCriteria 的主要區別
在於建立的形式不一樣, Criteria 是線上的,所以它是由 Hibernate Session 進行建立的,而 DetachedCriteria 是離線的,建立時無需Session .
DetachedCriteria的建立

DetachedCriteria 提供了 2 個靜態方法 ,進行DetachedCriteria 例項的建立。
forClass(Class)
forEntityName(Name)

Spring 的框架提供了對於離線查詢的支援,非常的簡單的使用那些方法
Spring 的框架提供了getHibernateTemplate().findByCriteria(detachedCriteria) 方法可以很方便地根據DetachedCriteria 來返回查詢結果。Criteria的子類就是 DetachedCriteria 我們可以簡單的使用就好了。
使用到了這些我們就不得不說 Restrictions 是產生查詢條件的工具類。
當然你也可以手動這麼幹:

DetachedCriteria query = DetachedCriteria.forClass(Cat.class)
    .add( Property.forName("sex").eq(`F`) );
//建立一個Session
Session session = .;
Transaction txn = session.beginTransaction();
List results = query.getExecutableCriteria(session).setMaxResults(100).list();
txn.commit();
session.close();

切記,DetachedCriteria例項不要去重用它

DetachedCriteria作為子查詢

//主查詢:人員查詢
DetachedCriteria searDc =
DetachedCriteria.forClass(QymlPerson.class);

//子查詢:職務人員關係表
DetachedCriteria sub =
DetachedCriteria.forClass(QymlPositionUserLink.class);
sub.add(Restrictions.eq("positionunid", positionunid));
//子查詢:指定查詢的列(也就是select usernuid from ....)
sub.setProjection(Property.forName("userunid"));

//主查詢和子查詢關聯(也就是where unid in (select userunid from...) )
searDc.add(Property.forName("unid").in(sub));

在上面的例子中,用個一個類似於下面SQL 的子查詢

Select * from Person a where a.unid in (select userunid from PositionUserLink b where
b.positionunid = ..)

Property 還有其他的條件判斷,參考api
http://docs.jboss.org/hiberna…
ion/Property.html。

動態關聯抓取

我們的抓取模式,對於1對多的關聯的形式!是不是抓取過來呢?
你可以使用setFetchMode()在執行時定義動態關聯抓取的語義

List cats = sess.createCriteria(Cat.class)
    .add( Restrictions.like("name", "Fritz%") )
    .setFetchMode("mate", FetchMode.JOIN)
    .setFetchMode("kittens", FetchMode.JOIN)
    .list();
    

這個查詢可以通過外連線抓取mate和kittens。

參考:http://blog.csdn.net/u0128819…
http://blog.sina.com.cn/s/blo…

問題十二、投影(Projections)、聚合(aggregation)和分組(grouping)

org.hibernate.criterion.ProjectionsProjection 的例項工廠。
我們通過呼叫setProjection()應用投影到一個查詢。這個的意思就是查詢哪一列的意思
用來進行聚合操作,和sql中的聚合類似.求和/求平均值/統計記錄數/…等等.
還有用來獲取獲取物件的某些屬性(表欄位)或屬性集合.正常情況下,查詢返回的是物件或物件的集合.使用投影的話就可以只返回你需要的屬性值.此時,即Hibernate不把記錄封裝物件了,只返回你在投影中設定的屬性的值(值的集合)的陣列

List results = session.createCriteria(Cat.class)
    .setProjection( Projections.projectionList()
        .add( Projections.rowCount() )
        //當你新增一個投影到一個投影列表中時 你可以為它指定一個別名:如
        //.add( Projections.rowCount() ,"count")
        .add( Projections.avg("weight") )
        .add( Projections.max("weight") )
        .add( Projections.groupProperty("color") )
    )
    .list();

可以選擇把一個別名指派給一個投影,這樣可以使投影值被約束或排序所引用。下面是兩種不同的實現方式:

List results = session.createCriteria(Cat.class)
    .setProjection( Projections.alias( Projections.groupProperty("color"), "colr" ) )
    //.setProjection( Projections.groupProperty("color").as("colr") )
    .addOrder( Order.asc("colr") )
    .list();

也可以使用Property.forName()來表示投影:

List results = session.createCriteria(Cat.class)
    .setProjection( Projections.projectionList()
        .add( Projections.rowCount().as("catCountByColor") )
        .add( Property.forName("name"))
        .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();

參考:http://blog.csdn.net/u0128819…

相關文章