分享知識-快樂自己:Hibernate 中Criteria Query查詢詳解


1):Hibernate 中Criteria Query查詢詳解

當查詢數據時,人們往往需要設置查詢條件。在SQL或HQL語句中,查詢條件常常放在where子句中。

此外,Hibernate還支持Criteria查詢(Criteria Query),這種查詢方式把查詢條件封裝為一個Criteria對象。

在實際應用中,使用Session的createCriteria()方法構建一個org.hibernate.Criteria實例,然后把具體的查詢條件通過Criteria的add()方法加入到Criteria實例中。

這樣,程序員可以不使用SQL甚至HQL的情況下進行數據查詢,如例程9-1所示。

Criteria cr = session.createCriteria(Student.class); //生成一個Criteria對象
cr.add(Restrictions.eq("name", "Bill"));//等價於where name=’Bill’
List list = cr.list();
Student stu = (Student)list.get(0);
System.out.println(stu.getName());

Restrictions.eq()方法表示equal,即等於的情況。

Restrictions類提供了查詢限制機制。

它提供了許多方法,以實現查詢限制。

這些方法及其他一些criteria常用查詢限制方法列於表9-1中:

方 法

說 明

Restrictions.eq()

equal,=

Restrictions.allEq()

參數為Map對象,使用key/value進行多個等於的對比,相當於多個Restrictions.eq()的效果

Restrictions.gt()

greater-than, >

Restrictions.lt()

less-than, <

Restrictions.le()

less-equal, <=

Restrictions.between()

對應SQL的between子句

Restrictions.like()

對應SQL的like子句

Restrictions.in()

對應SQL的in子句

Restrictions.and()

and關系

Restrictions.or()

or關系

Restrictions.isNull()

判斷屬性是否為空,為空返回true,否則返回false

Restrictions.isNotNull()

與Restrictions.isNull()相反

Order.asc()

根據傳入的字段進行升序排序

Order.desc()

根據傳入的字段進行降序排序

MatchMode.EXACT

字符串精確匹配,相當於“like 'value'”

MatchMode.ANYWHERE

字符串在中間位置,相當於“like '%value%'”

MatchMode.START

字符串在最前面的位置,相當於“like 'value%'”

MatchMode.END

字符串在最后面的位置,相當於“like '%value'

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

例1:查詢學生名字以t開頭的所有Student對象。

Criteria cr = session.createCriteria(Student.class); cr.add(Restrictions.like(“name”, “t%”)) List list = cr.list(); Student stu = (Student)list.get(0);

或者使用另一種方式:

Criteria cr = session.createCriteria(Student.class); cr.add(Restrictions.like(“name”, “t”, MatchMode.START)) List list = cr.list(); Student stu = (Student)list.get(0);

例2:查詢學生姓名在Bill, Jack和Tom之間的所有Student對象。

String[] names = {“Bill”, “Jack”, “Tom”} Criteria cr = session.createCriteria(Student.class); cr.add(Restrictions.in(“name”, names)) List list = cr.list(); Student stu = (Student)list.get(0);

例3:查詢學生的年齡age等於22或age為空(null)的所有Student對象。

Criteria cr = session.createCriteria(Student.class); cr.add(Restrictions.eq(“age”, new Integer(22)); cr.add(Restrictions.isNull(“age”)); List list = cr.list(); Student stu = (Student)list.get(0);

例4:查詢學生姓名以字母F開頭的所有Student對象,並按姓名升序排序。

Criteria cr = session.createCriteria(Student.class); cr.add(Restrictions.like(“name”, “F%”); cr.addOrder(Order.asc(“name”)); List list = cr.list(); Student stu = (Student)list.get(0);

調用Order.asc的方法應是Criteria的addOrder()方法。

使用add()方法加入條件時,預設是使用and來組合條件,如果要用or的方式來組合條件,

則可以使用Restrictions.or()方法,例如結合age等於(eq)20或(or)age為空(isNull)的條件:

Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.or(
Restrictions.eq("age", new Integer(20)),
Restrictions.isNull("age")
));
List users = criteria.list();

觀察所產生的SQL語句,將使用where與or子句完成SQL的條件查詢:

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)

使用Criteria進行查詢時,不僅僅能組合出SQL中where子句的功能,還可以組合出如排序、統計、分組等的查詢功能。

這就是Criteria進階查詢。

排序:

您可以使用Criteria進行查詢,並使用org.hibernate.criterion.Order對結果進行排序,例如使用Oder.asc(),指定根據”age”由小到大排序(反之則使用desc()):

Criteria criteria = session.createCriteria(User.class); criteria.addOrder(Order.asc("age")); List users = criteria.list();

注意:在加入Order條件時,使用的是addOrder()方法,而不是add()方法,在產生SQL語句時,會使用order by與asc(desc)來進行排序指定:

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

限定查詢筆數:

Criteria的setMaxResults()方法可以限定查詢回來的筆數,如果配合setFirstResult()設定傳回查詢結果第一筆資料的位置,

就可以實現簡單的分頁,例如傳回第51筆之后的50筆資料(如果有的話):

Criteria criteria = session.createCriteria(User.class); criteria.setFirstResult(51); criteria.setMaxResults(50); List users = criteria.list();

根據您所指定得資料庫,Hibernate將自動產生與資料庫相依的限定筆數查詢子句,例如在MySQL中,將使用limit產生以下的SQL語句:

Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ limit ?, ?

統計動作:

您可以對查詢結果進行統計動作,使用 org.hibernate.criterion.Projections的avg()、rowCount()、count()、max()、min ()、 countDistinct()等方法,

再搭配Criteria的setProjection()方法加入條件設定,例如對查詢結果的"age"作平均:

Criteria criteria = session.createCriteria(User.class); criteria.setProjection(Projections.avg("age")); List users = criteria.list();

上面的程式將由Hibernate自動產生SQL的avg函數進行平均計算:

Hibernate: select avg(this_.age) as y0_ from T_USER this_

分組:

還可以配合Projections的groupProperty()來對結果進行分組,例如以"age"進行分組,也就是如果資料中"age"如果有 20、20、25、30,則以下會顯示20、25、30:

Criteria criteria = session.createCriteria(User.class); criteria.setProjection(Projections.groupProperty("age")); List users = criteria.list();

上面的程式將由Hibernate自動產生SQL的group by子句進行分組計算:

Hibernate: select this_.age as y0_ from T_USER this_ group by this_.age

如果想同時結合統計與分組功能,則可以使用org.hibernate.criterion.ProjectionList,例如下面的程式會計算每個年齡各有多少個人:

ProjectionList projectionList = Projections.projectionList(); projectionList.add(Projections.groupProperty("age")); projectionList.add(Projections.rowCount()); Criteria criteria = session.createCriteria(User.class); criteria.setProjection(projectionList); List users = criteria.list();

 觀察所產生的SQL語句,將使用group by先進行分組,再針對每個分組進行count函數的計數,

Hibernate: select this_.age as y0_, count(*) as y1_ from T_USER this_ group by this_.age

根據已知物件進行查詢:

設定查詢條件並非一定要使用Restrictions,如果屬性條件很多,使用Restrictions也不方便,

如果有一個已知的物件,則可以根據這個物件作為查詢的依據,看看是否有屬性與之類似的物件,例如:

User user = new User(); user.setAge(new Integer(30)); Criteria criteria = session.createCriteria(User.class); criteria.add(Example.create(user)); List users = criteria.list();

Criteria進階查詢中,您可以透過 org.hibernate.criterion.Example的create()方法來建立Example實例,Example實作了 Criteria介面,

因此可以使用add()方法加入至Criteria條件設定之中,Hibernate將自動過濾掉空屬性,根據已知物件上已設定的屬性,判定是否產生於where子句之中:

Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where (this_.age=?)

設定SQL范本:

如果您了解如何撰寫SQL語句,想要設定一些Hibernate產生SQL時的范本,您也可以使用Restrictions的sqlRestriction()方法,

提供SQL語法范本作限定查詢,例如查詢name以cater開頭的資料:

Criteria criteria = session.createCriteria(User.class); criteria.add(Restrictions.sqlRestriction( "{alias}.name LIKE (?)", "cater%", Hibernate.STRING)); List users = criteria.list();

其中alias將被替換為與User類別相關的名稱,而? 將被替換為cater%,也就是第二個參數所提供的值,sqlRestriction()方法第一個參數所設定的是where子句的部份,

所以在SQL撰寫時,不必再寫where,觀察所產生的SQL語句,將使用您所設定的SQL范本作為基礎,來完成SQL的條件查詢:

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 (?)

如果有多個查詢條件,例如between子句的查詢,則可以如下:

Criteria criteria = session.createCriteria(User.class); Integer[] ages = {new Integer(20), new Integer(40)}; Type[] types = {Hibernate.INTEGER, Hibernate.INTEGER}; criteria.add(Restrictions.sqlRestriction( "{alias}.age BETWEEN (?) AND (?)", ages, types)); List users = criteria.list();

觀察所產生的SQL語句如下:

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 (?)

 

2):連接限制

在Criteria 查詢中使用FetchMode來實現連接限制。在HQL語句中,可以通過fetch關鍵字來表示預先抓取(Eager fetching),如下所示:

from Group g left join fetch g.students s where g.name like ' 05'

可以使用Criteria的API完成同樣的功能,如下所示:

Criteria cr = session.createCriteria(Group.class); cr.setFetchMode(“students”, FetchMode.EAGER); cr.add(Restrictions.like(“name”, “2005”, MatchMode.END)) List list = cr.list();

以上兩種方式編寫的代碼,都使用相同的SQL語句完成它們的功能,如下所示:

select g.*, s.* from Group g left outer join Student s on g.id = s.group_id where g.name like ' 05'

 

/**-**/:一輩子很短,努力的做好兩件事就好;第一件事是熱愛生活,好好的去愛身邊的人;第二件事是努力學習,在工作中取得不一樣的成績,實現自己的價值,而不是僅僅為了賺錢;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM