<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Dev@Free

    zJun's Tech Weblog

    使用Criteria進(jìn)行查詢 by 林信良(良葛格)

    要對(duì)資料庫管理系統(tǒng)進(jìn)行操作,最基本的就是使用SQL(Standard Query Language)語句,大部份的資料庫都支援標(biāo)準(zhǔn)的SQL語句,然而也有一些特定於資料庫的SQL語句,應(yīng)用程式配合SQL語句進(jìn)行資料庫查詢時(shí),若使用到特定於資料庫的SQL語句,程式本身會(huì)有相依於特定資料庫的問題。

    使用Hibernate時(shí),即使您不了解SQL的使用與撰寫,也可以使用它所提供的API來進(jìn)行SQL語句查詢,org.hibernate.Criteria對(duì)SQL進(jìn)行封裝,您可以從Java物件的觀點(diǎn)來組合各種查詢條件,由Hibernate自動(dòng)為您產(chǎn)生SQL語句,而不用特別管理SQL與資料庫相依的問題。

    以最基本的查詢來說,如果您想要查詢某個(gè)物件所對(duì)應(yīng)的資料表中所有的內(nèi)容,您可以如下進(jìn)行查詢:

    				Criteria criteria = session.createCriteria(User.class);
    				List users = criteria.list();
    				    	
    				for(Iterator it = users.iterator(); it.hasNext(); ) {
    				    User user = (User) it.next();
    				    System.out.println(user.getId() +
    				                             " \t " + user.getName() +
    				                          "/" + user.getAge());    
    				} 
    
    				

    Criteria建立後,若不給予任何的條件,預(yù)設(shè)是查詢物件所對(duì)應(yīng)表格之所有資料,如果您執(zhí)行以上的程式片段,並於設(shè)定檔中設(shè)定了了Hibernate的”show_sql”屬性,則可以在主控下看到以下的SQL語句之產(chǎn)生:

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

    Criteria基本查詢條件設(shè)定

    org.hibernate.Criteria實(shí)際上是個(gè)條件附加的容器,如果想要設(shè)定查詢條件,則要使用org.hibernate.criterion.Restrictions的各種靜態(tài)方法傳回org.hibernate.criterion.Criteria實(shí)例,傳回的每個(gè)org.hibernate.criterion.Criteria實(shí)例代表著一個(gè)條件,您要使用org.hibernate.Criteria的add()方法加入這些條件實(shí)例,例如查詢”age”大於20且小於40的資料:

    				Criteria criteria = session.createCriteria(User.class);
    				criteria.add(Restrictions.gt("age", new Integer(20)));
    				criteria.add(Restrictions.lt("age", new Integer(40)));
    				List users = criteria.list();
    				    	
    				for(Iterator it = users.iterator(); it.hasNext(); ) {
    				    User user = (User) it.next();
    				    System.out.println(user.getId() +
    				                              " \t " + user.getName() +
    				                             "/" + user.getAge());    
    				}	
    				

    Restrictions的gt()方法表示大於(great than)的條件,而lt表示小於(less than)的條件,執(zhí)行以上程式片段,觀察所產(chǎn)生的SQL語句,將使用where與and子句產(chǎn)來完成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>? and this_.age

    使用add()方法加入條件時(shí),預(yù)設(shè)是使用and來組合條件,如果要用or的方式來組合條件,則可以使用Restrictions.or()方法,例如結(jié)合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();
    				

    觀察所產(chǎn)生的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)

    您也可以使用Restrictions.like()方法來進(jìn)行SQL中l(wèi)ike子句的功能,例如查詢”name”中名稱為”just”開頭的資料:

    				Criteria criteria = session.createCriteria(User.class);
    				criteria.add(Restrictions.like("name", "just%"));
    				List users = criteria.list();
    				

    觀察所產(chǎn)生的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 ?

    Restrictions的幾個(gè)常用限定查詢方法如下表所示:

    方法 說明
    Restrictions.eq 等於
    Restrictions.allEq 使用Map,使用key/value進(jìn)行多個(gè)等於的比對(duì)
    Restrictions.gt 大於 >
    Restrictions.ge 大於等於 >=
    Restrictions.lt 小於 <
    Restrictions.le 小於等於 <=
    Restrictions.between 對(duì)應(yīng)SQL的BETWEEN子句
    Restrictions.like 對(duì)應(yīng)SQL的LIKE子句
    Restrictions.in 對(duì)應(yīng)SQL的in子句
    Restrictions.and and關(guān)係
    Restrictions.or or關(guān)係

    Criteria進(jìn)階查詢條件設(shè)定

    使用Criteria進(jìn)行查詢時(shí),不僅僅能組合出SQL中where子句的功能,還可以組合出如排序、統(tǒng)計(jì)、分組等的查詢功能。

    排序

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

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

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

    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

    限定查詢筆數(shù)

    Criteria的setMaxResults()方法可以限定查詢回來的筆數(shù),如果配合setFirstResult()設(shè)定傳回查詢結(jié)果第一筆資料的位置,就可以實(shí)現(xiàn)簡(jiǎn)單的分頁,例如傳回第51筆之後的50筆資料(如果有的話):

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

    根據(jù)您所指定得資料庫,Hibernate將自動(dòng)產(chǎn)生與資料庫相依的限定筆數(shù)查詢子句,例如在MySQL中,將使用limit產(chǎn)生以下的SQL語句:

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

    統(tǒng)計(jì)動(dòng)作

    您可以對(duì)查詢結(jié)果進(jìn)行統(tǒng)計(jì)動(dòng)作,使用org.hibernate.criterion.Projections的avg()、rowCount()、count()、max()、min()、 countDistinct()等方法,再搭配Criteria的setProjection()方法加入條件設(shè)定,例如對(duì)查詢結(jié)果的"age"作平均:

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

    上面的程式將由Hibernate自動(dòng)產(chǎn)生SQL的avg函數(shù)進(jìn)行平均計(jì)算:

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

    分組

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

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

    上面的程式將由Hibernate自動(dòng)產(chǎn)生SQL的group by子句進(jìn)行分組計(jì)算:

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

    如果想同時(shí)結(jié)合統(tǒng)計(jì)與分組功能,則可以使用org.hibernate.criterion.ProjectionList,例如下面的程式會(huì)計(jì)算每個(gè)年齡各有多少個(gè)人:

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

    觀察所產(chǎn)生的SQL語句,將使用group by先進(jìn)行分組,再針對(duì)每個(gè)分組進(jìn)行count函數(shù)的計(jì)數(shù)

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

    根據(jù)已知物件進(jìn)行查詢

    設(shè)定查詢條件並非一定要使用Restrictions,如果屬性條件很多,使用Restrictions也不方便,如果有一個(gè)已知的物件,則可以根據(jù)這個(gè)物件作為查詢的依據(jù),看看是否有屬性與之類似的物件,例如:

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

    您可以透過org.hibernate.criterion.Example的create()方法來建立Example實(shí)例,Example實(shí)作了Criteria介面,因此可以使用add()方法加入至Criteria條件設(shè)定之中,Hibernate將自動(dòng)過濾掉空屬性,根據(jù)已知物件上已設(shè)定的屬性,判定是否產(chǎn)生於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=?)

    設(shè)定SQL範(fàn)本

    如果您了解如何撰寫SQL語句,想要設(shè)定一些Hibernate產(chǎn)生SQL時(shí)的範(fàn)本,您也可以使用Restrictions的sqlRestriction()方法,提供SQL語法範(fàn)本作限定查詢,例如查詢name以cater開頭的資料:

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

    其中alias將被替換為與User類別相關(guān)的名稱,而?將被替換為cater%,也就是第二個(gè)參數(shù)所提供的值,sqlRestriction()方法第一個(gè)參數(shù)所設(shè)定的是where子句的部份,所以在SQL撰寫時(shí),不必再寫where,觀察所產(chǎn)生的SQL語句,將使用您所設(shè)定的SQL範(fàn)本作為基礎(chǔ),來完成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 (?)

    如果有多個(gè)查詢條件,例如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();				
    				

    觀察所產(chǎn)生的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 (?)

    使用DetchedCriteria

    Criteria與Session綁定,其生命週期跟隨著Session結(jié)束而結(jié)束,使用Criteria時(shí)進(jìn)行查詢時(shí),每次都要於執(zhí)行時(shí)期動(dòng)態(tài)建立物件,並加入各種查詢條件,隨著Session的回收,Criteria也跟著回收。

    為了能夠重複使用Criteria物件,在Hibernate 3中新增了org.hibernate.criterion.DetchedCriteria,您可以先建立DetchedCriteria實(shí)例,並加入各種查詢條件,並於需要查詢時(shí)再與Session綁定,獲得一個(gè)綁定Session的Criteria物件,例如:

    				// 先建立DetchedCriteria物件
    				DetachedCriteria detchedCriteria = DetachedCriteria.forClass(User.class);
    				// 加入查詢條件
    				detchedCriteria.add(Restrictions.ge("age",new Integer(25)));
    				       
    				Session session = sessionFactory.openSession();
    				// 綁定Session並返回一個(gè)Criteria實(shí)例
    				Criteria criteria = detchedCriteria.getExecutableCriteria(session);
    				       
    				List users = criteria.list();				
    				

    結(jié)論

    Hibernate的Criteria API可以讓您使用物件的方式,組合出查詢資料庫系統(tǒng)的條件,Hibernate會(huì)自動(dòng)依您所使用的資料庫,動(dòng)態(tài)產(chǎn)生SQL語句,讓您的應(yīng)用程式在存取資料庫時(shí),不致於因撰寫了特定的SQL而相依於特定的資料庫,如果您的開發(fā)人員不熟悉SQL語句的撰寫,也可以試著使用Criteria來解決查詢資料庫的需求。

    posted on 2007-10-11 16:22 zJun's帛羅閣 閱讀(15460) 評(píng)論(0)  編輯  收藏 所屬分類: 開源軟件

    導(dǎo)航

    <2007年10月>
    30123456
    78910111213
    14151617181920
    21222324252627
    28293031123
    45678910

    統(tǒng)計(jì)

    常用鏈接

    留言簿(15)

    隨筆分類

    隨筆檔案

    相冊(cè)

    收藏夾

    博客

    文檔

    站點(diǎn)

    論壇

    搜索

    積分與排名

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 天天拍拍天天爽免费视频| 久久久久久亚洲精品成人| 五月亭亭免费高清在线| 日韩毛片在线免费观看| 亚洲人成www在线播放| 亚洲综合视频在线| 亚洲乱码国产一区三区| 亚洲精品动漫人成3d在线 | 亚洲精品无码精品mV在线观看 | 亚洲第一成年网站视频| 亚洲女人初试黑人巨高清| 久久精品国产亚洲AV网站| 不卡精品国产_亚洲人成在线| 国产一级高清视频免费看| 无码视频免费一区二三区| 在线观看成人免费视频不卡| 日韩精品极品视频在线观看免费| 夜夜爽妓女8888视频免费观看| 理论亚洲区美一区二区三区| 亚洲精品动漫免费二区| 亚洲自偷自偷在线成人网站传媒 | 国产精品视频免费| 222www在线观看免费| 日韩免费高清大片在线| 免费在线看黄网站| 日韩精品免费视频| 色猫咪免费人成网站在线观看| 精品在线免费观看| 久久成人免费电影| 98精品全国免费观看视频| 8x成人永久免费视频| 57pao一国产成永久免费| 6080午夜一级毛片免费看 | 亚洲日韩在线观看| 国产啪亚洲国产精品无码| 爱情岛论坛网亚洲品质自拍| 亚洲日产无码中文字幕| 久久青青草原亚洲AV无码麻豆| 亚洲av日韩av激情亚洲| 亚洲女人初试黑人巨高清| 亚洲欧美一区二区三区日产|