10 07Hibernate之數據查詢

1 Session查詢

Session接口裏面本身所定義的數據查詢只有一個根據ID查詢的操作方法,但是這個方法卻有兩個定義:
(1)根據主鍵查詢:public <T> T get(Class<T> entityType, Serializable id)
(2)根據主鍵查詢:public <T> T load(Class<T> theClass, Serializable id)
兩個操作方法上只差了一個單詞,那麼使用上有差別嗎?
範例:使用get()查詢

package org.lks.test;

import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.News;

public class TestNewsGet {

	public static void main(String[] args) {
		News vo = HibernateSessionFactory.getSession().get(News.class, 100);
		System.out.println(vo);
		HibernateSessionFactory.closeSession();
	}
}
Hibernate: 
    select
        news0_.nid as nid1_0_0_,
        news0_.ntitle as ntitle2_0_0_,
        news0_.nvisits as nvisits3_0_0_,
        news0_.nitem as nitem4_0_0_ 
    from
        hedb.news news0_ 
    where
        news0_.nid=?
null
package org.lks.test;

import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.News;

public class TestNewsGet {

	public static void main(String[] args) {
		News vo = HibernateSessionFactory.getSession().load(News.class, 100);
		System.out.println(vo);
		HibernateSessionFactory.closeSession();
	}
}

Hibernate: 
    select
        news0_.nid as nid1_0_0_,
        news0_.ntitle as ntitle2_0_0_,
        news0_.nvisits as nvisits3_0_0_,
        news0_.nitem as nitem4_0_0_ 
    from
        hedb.news news0_ 
    where
        news0_.nid=?
Exception in thread "main" org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [org.lks.pojo.News#100]

使用load()查詢的時候如果指定的ID不存在,那麼就會出現異常。
面試題:請問Hibernate中get()與load()方法有什麼區別?
(1)get()與load()方法都是在Session接口中定義的根據主鍵查詢的操作;
(2)get()方法查詢時,如果主鍵不存在,則返回null;
(3)load()方法查詢時,如果主鍵不存,則拋出異常。

2 Query查詢

面對數據操作中,數據的查詢部分永遠都是最爲複雜的部分,所以來講如果要進行更加合理的查詢操作,那麼必須依靠Query接口來實現,而如果要想取得此接口的實例化對象,必須依靠Session接口完成,在Session接口中定義有如下方法:
(1)取得Query接口對象:public Query createQuery(String queryString)
|————此處表示傳入一個hql語法進行數據查詢(Hibernate Query Language)
在Query接口裏面主要定義瞭如下幾個操作方法:
(1)設置要操作的數據:【Deprecated】default Query<R> setXxx(int position, 數據類型 val)
|————(since 5.2) use setParameter(int, Object) or setParameter(int, Object, Type) instead
Bind a positional float-valued parameter.
(2)設置參數:public Query<R> setParameter(int position, Object value)
(3)取得單個查詢結果:public R uniqueResult()
(4)查詢全部數據:public List<R> list()
(5)數據更新:public int executeUpdate()

2.1 數據查詢

在Hibernate裏面Session查詢不能夠勝任於複雜查詢,所以現在的所有查詢都通過Query接口完成,那麼在這個接口裏面要使用hql語言(極其類似於SQL語句)。
範例:查詢全部數據

package org.lks.test;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Query;
import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.News;

public class QueryDemoA {

	public static void main(String[] args) {
		String hql = "FROM News AS n"; //hql查詢全部
		Query query = HibernateSessionFactory.getSession().createQuery(hql);
		List<News> all = query.list();
		Iterator<News> iter = all.iterator();
		while(iter.hasNext()){
			System.out.println(iter.next());
		}
		HibernateSessionFactory.closeSession();
	}
}

現在通過以上的代碼可以發現如下幾點:
(1)在Hibernate裏面使用的都是HQL,但是在使用HQL的時候一定要注意,FROM子句之後跟的是POJO類的名字,必須注意大小寫News.java(News),而AS指的就是別名,一般情況下可以省略。
(2)在使用Hibernate進行數據查詢的時候,發現所有的內容都會自動以POJO類的形式返回,所有的實例化的操作部分都由Hibernate自動幫助用戶處理了;

所謂的HQL其語法的結構非常類似於SQL語法結構,那麼也可以編寫SELECT語句,但是大部分人不會這麼寫。
範例:查詢指定的數據列

package org.lks.test;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Query;
import org.lks.dbc.HibernateSessionFactory;

public class QueryDemoA {

	public static void main(String[] args) {
		String hql = "SELECT n.ntitle,n.nitem FROM News AS n"; //hql查詢全部
		Query query = HibernateSessionFactory.getSession().createQuery(hql);
		List<Object[]> all = query.list();
		Iterator<Object[]> iter = all.iterator();
		while(iter.hasNext()){
			Object[] obj = iter.next();
			System.out.println(obj[0] + ", " + obj[1]);
		}
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

此時的代碼的確是進行了數據列的操作限制,但是其結果發現爲了保證查詢,那麼返回的數據不再自動轉化爲News這個POJO類,而是以對象數組的形式返回,相比較自動匹配POJO類型,以上的操作明顯不方便。

Hibernate在設計的時候考慮到了以上的情況,所以在Hibernate裏面提供有一個專門負責轉換處理的類(org.hibernate.transform.AliasToBeanResultTransformer),但是即便轉換了你也需要做一些輔助性的操作。隨後在Query接口裏面使用如下的轉換操作方法明確設置:
(1)設置結果轉換:【Deprecated】default Query<R> setParameters(Object[] values, Type[] types)
範例:手工轉換

package org.lks.test;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.transform.AliasToBeanResultTransformer;
import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.News;

public class QueryDemoC {

	public static void main(String[] args) {
		String hql = "SELECT n.ntitle AS ntitle,n.nitem AS nitem FROM News AS n"; //hql查詢全部
		Query query = HibernateSessionFactory.getSession().createQuery(hql);
		query.setResultTransformer(new AliasToBeanResultTransformer(News.class));
		List<News> all = query.list();
		Iterator<News> iter = all.iterator();
		while(iter.hasNext()){
			System.out.println(iter.next());
		}
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

在本代碼之中實際上只是一個功能的演示,如果真查詢,就查詢全部數據,千萬別做部分數據的查詢。

那麼既然可以實現查詢全部的操作,就一定可以實現根據ID查詢的操作,也就是說使用限定查詢。
範例:在Query中實現限定查詢

package org.lks.test;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.transform.AliasToBeanResultTransformer;
import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.News;

public class QueryDemoD {

	public static void main(String[] args) {
		String hql = "FROM News AS n WHERE n.nid=?"; //hql查詢全部
		Query query = HibernateSessionFactory.getSession().createQuery(hql);
//		query.setInteger(0, 3);
		query.setParameter(0, 3);  //所有的類型由Hibernate自己處理
		News vo = (News) query.uniqueResult();
		System.out.println(vo);
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

模糊查詢在Query中可以繼續像SQL那樣直接使用。
範例:實現模糊查詢

package org.lks.test;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.transform.AliasToBeanResultTransformer;
import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.News;

public class QueryDemoE {

	public static void main(String[] args) {
		String column = "ntitle";
		String keyWord = "lks";
		String hql = "FROM News AS n WHERE n." + column + " LIKE ?"; //hql查詢全部
		Query query = HibernateSessionFactory.getSession().createQuery(hql);
		query.setParameter(0, "%" + keyWord + "%");
		List<News> all = query.list();
		Iterator<News> iter = all.iterator();
		while(iter.hasNext()){
			System.out.println(iter.next());
		}
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

各個數據庫之中最麻煩的在於分頁的支持不同,而Hibernate是一個跨數據庫的工具,所以裏面的分頁將使用統一的放式進行處理,在Query接口裏面定義有兩個操作方法:
(1)設置開始行:public Query<R> setFirstResult(int startPosition)
(2)設置最大返回行:Query<R> setMaxResults(int maxResult)
範例:數據分頁

package org.lks.test;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.transform.AliasToBeanResultTransformer;
import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.News;

public class QueryDemoF {

	public static void main(String[] args) {
		int currentPage = 2;
		int lineSize = 3;
		String column = "ntitle";
		String keyWord = "";
		String hql = "FROM News AS n WHERE n." + column + " LIKE ?"; //hql查詢全部
		Query query = HibernateSessionFactory.getSession().createQuery(hql);
		query.setParameter(0, "%" + keyWord + "%");
		query.setFirstResult((currentPage - 1) * lineSize);
		query.setMaxResults(lineSize);
		List<News> all = query.list();
		Iterator<News> iter = all.iterator();
		while(iter.hasNext()){
			System.out.println(iter.next());
		}
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

不管是什麼數據庫,只要設置了分頁都會由Hibernate自己進行適應。

在Query接口裏面如果要進行數據統計的話,那麼就必須編寫SELECT語句了。但是統計的個數只有唯一的一個。
範例:統計數據個數

package org.lks.test;

import org.hibernate.Query;
import org.lks.dbc.HibernateSessionFactory;

public class QueryDemoG {

	public static void main(String[] args) {
		String column = "ntitle";
		String keyWord = "";
		String hql = "SELECT COUNT(*) FROM News AS n WHERE n." + column + " LIKE ?";
		Query query = HibernateSessionFactory.getSession().createQuery(hql);
		query.setParameter(0, "%" + keyWord + "%");
		System.out.println(query.uniqueResult());
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

Hibernate中返回的數據個數的統計結果類型爲Long。

編寫HQL的時候實際上也可以進行分組統計查詢。
範例:實現分組統計查詢

package org.lks.test;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.hibernate.Query;
import org.lks.dbc.HibernateSessionFactory;

public class QueryDemoG {

	public static void main(String[] args) {
		String column = "ntitle";
		String keyWord = "";
		String hql = "SELECT n.nitem,COUNT(*) AS ncount,SUM(n.nvisits) AS nsum "
				+ "FROM News AS n WHERE n." + column 
				+ " LIKE ? GROUP BY n.nitem HAVING SUM(n.nvisits)>50";
		Query query = HibernateSessionFactory.getSession().createQuery(hql);
		query.setParameter(0, "%" + keyWord + "%");
		List<Object[]> all = query.list();
		Iterator<Object[]> iter = all.iterator();
		while(iter.hasNext()){
			System.out.println(Arrays.toString(iter.next()));
		}
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

如果需要在Query查詢之中爲查詢列設置別名的話,一定要加上AS,否則無效。

2.2 使用SQL查詢(不建議使用)

即使HQL的語法很像SQL語法,但是它依然不是SQL,所以很多時候可能支持度有限。所以爲了解決這樣的問題,在Hibernate裏面也可以使用普通的SQL語句進行數據的查詢,但是如果要想將查詢結果變爲POJO類的形式,則必須使用轉換操作。

如果要創建SQL查詢,在Session接口裏面定義有如下方法:
(1)創建SQL查詢:public NativeQuery createSQLQuery(String queryString)
範例:使用SQL查詢

package org.lks.test;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.transform.AliasToBeanResultTransformer;
import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.News;

public class QueryDemoI {

	public static void main(String[] args) {
		String hql = "SELECT ntitle,nitem FROM news";
		Query query = HibernateSessionFactory.getSession().createSQLQuery(hql);
		query.setResultTransformer(new AliasToBeanResultTransformer(News.class));
		List<News> all = query.list();
		Iterator<News> iter = all.iterator();
		while(iter.hasNext()){
			System.out.println(iter.next());
		}
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

既然都已經擺脫了PreparedStatement接口了,那麼這樣的操作不寫也罷。

2.3 查詢佔位符

在之前編寫的時候使用的HQL的佔位符都是?(推薦做法),但是在HQL裏面對於佔位符還有另外一種形式使用:名稱描述,這樣的目的主要是爲了解決設置的內容過多的時候,?容易數不清楚。
範例:使用其它佔位符

package org.lks.test;

import org.hibernate.Query;
import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.News;

public class QueryDemoJ {

	public static void main(String[] args) {
		String hql = "FROM News AS n WHERE n.nid=:pnid"; //hql查詢全部
		Query query = HibernateSessionFactory.getSession().createQuery(hql);
//		query.setInteger(0, 3);
		query.setParameter("pnid", 3);  //所有的類型由Hibernate自己處理
		News vo = (News) query.uniqueResult();
		System.out.println(vo);
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

那麼此時有人提出來了,能不能?和佔位符一起使用呢?如果要混合使用,那麼請將?寫在:之前。
範例:混合使用

package org.lks.test;

import org.hibernate.Query;
import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.News;

public class QueryDemoJ {

	public static void main(String[] args) {
		String hql = "FROM News AS n WHERE n.nitem=? AND n.nid=:pnid"; //hql查詢全部
		Query query = HibernateSessionFactory.getSession().createQuery(hql);
//		query.setInteger(0, 3);
		query.setParameter(0, "笨蛋");
		query.setParameter("pnid", 3);  //所有的類型由Hibernate自己處理
		News vo = (News) query.uniqueResult();
		System.out.println(vo);
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

雖然支持:的佔位符,但是正常人都使用?完成。

2.4 在配置文件中編寫HQL(不推薦)

有些人認爲對於HQL操作如果直接寫在程序之中可能會比較混亂,希望可以將HQL和查詢分開,如果要想不分開那麼必須藉助於*.hbm.xml文件完成。
範例:在News.hbm.xml文件裏面增加如下的查詢配置(在根節點之下編寫)

<query name="findById">
	FROM News AS n WHERE n.nid=?
</query>

那麼自然要在程序之中讀取這樣的配置信息。
範例:讀取配置的查詢信息

package org.lks.test;

import org.hibernate.Query;
import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.News;

public class QueryDemoL {

	public static void main(String[] args) {
		//讀取配置文件中的findByID配置的元素內容
		Query query = HibernateSessionFactory.getSession().getNamedQuery("findById");
		query.setParameter(0, 3);  //所有的類型由Hibernate自己處理
		News vo = (News) query.uniqueResult();
		System.out.println(vo);
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

這些只是Hibernate發展初期的時候,所遺留的一些功能,但是沒有實用性。

2.5 更新操作

在Hibernate最早設計的時候,所有的更新操作只能夠通過update()方法或者是delete()執行,但是隨着時間的發展,發現一個問題,如果使用這些方法無法實現部分數據的更新。

從Hibernate 2.x開始針對於Query接口實現了功能的擴充,讓其可以實現數據更新操作。
範例:使用Query接口更新數據

package org.lks.test;

import org.hibernate.Query;
import org.lks.dbc.HibernateSessionFactory;

public class QueryUpdateA {

	public static void main(String[] args) {
		String hql = "UPDATE News SET ntitle=?,nvisits=? WHERE nid=?";
		Query query = HibernateSessionFactory.getSession().createSQLQuery(hql);
		query.setParameter(0, "play backetball");
		query.setParameter(1, 20000);
		query.setParameter(2, 5);
		int len = query.executeUpdate();
		System.out.println(len);
		HibernateSessionFactory.getSession().beginTransaction().commit();
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

範例:實現數據刪除操作

package org.lks.test;

import org.hibernate.Query;
import org.lks.dbc.HibernateSessionFactory;

public class QueryDelete {

	public static void main(String[] args) {
		String hql = "DELETE FROM News WHERE nid=?";
		Query query = HibernateSessionFactory.getSession().createSQLQuery(hql);
		query.setParameter(0, 1);
		int len = query.executeUpdate();
		System.out.println(len);
		HibernateSessionFactory.getSession().beginTransaction().commit();
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

雖然此處實現了更新操作,但是在Query接口上設計有些不妥,不過這個不妥也都成爲習慣了。

3 Criteria接口

大部分情況下如果要使用查詢操作,首選的一定是HQL查詢,但是在Hibernate之中有一個特殊情況,:Hibernate屬於ORMapping的映射框架,那麼如果是ORMapping的映射框架,所有的操作都應該以對象爲主進行使用,那麼Query的使用就不符合於這種要求了,所以在查詢的基礎上又擴充了一個基於對象模式的查詢接口:Criteria接口,而這個接口的創建依靠Session接口:【Deprecated】public Criteria createCriteria(Class persistentClass)
範例:查詢全部數據

package org.lks.test;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Criteria;
import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.News;

public class CriteriaDemoA {

	public static void main(String[] args) {
		Criteria criteria = HibernateSessionFactory.getSession().createCriteria(News.class);
		List<News> all = criteria.list();
		Iterator<News> iter = all.iterator();
		while(iter.hasNext()){
			News vo = iter.next();
			System.out.println(vo);
		}
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

如果只是這種簡單的查詢,那麼使用Criteria接口一定要比使用Query接口更加的容易。

但實際的開發之中,雖然需要查詢全部,但是很多時候都會需要限定查詢,所以在Criteria裏面也支持查詢條件的設置,此接口定義瞭如下一個增加查詢條件的方法:public Criteria add(Criterion criterion)

那麼這個時候對於所有的條件的創建還需要使用另外一個類:org.hibernate.criterion.Restrictions,這個類定義瞭如下幾個操作的方法:
(1)邏輯運算:
|——與運算(AND):public static Conjunction and(Criterion... predicates)
|——或運算(OR):public static Disjunction or(Criterion... predicates)
|——非運算(NOT):public static Criterion not(Criterion expression)
(2)關係運算:
|——==public static SimpleExpression eq(String propertyName, Object value)
|——!=public static SimpleExpression ne(String propertyName, Object value)
|——>public static SimpleExpression gt(String propertyName, Object value)
|——>=public static SimpleExpression ge(String propertyName, Object value)
|——<public static SimpleExpression lt(String propertyName, Object value)
|——<=public static SimpleExpression le(String propertyName, Object value)
|——LIKEpublic static SimpleExpression like(String propertyName, Object value)
|——INpublic static Criterion in(String propertyName, Collection values)
|——BETWEEN..AND..public static Criterion between(String propertyName, Object low, Object high)
|——ISNULLpublic static Criterion isNull(String propertyName)
|——ISNOTNULLpublic static Criterion isNotNull(String propertyName)
範例:根據ID查詢

package org.lks.test;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.News;

public class CriteriaDemoB {

	public static void main(String[] args) {
		Criteria criteria = HibernateSessionFactory.getSession().createCriteria(News.class);
		criteria.add(Restrictions.eq("nid", 3));
		List<News> all = criteria.list();
		Iterator<News> iter = all.iterator();
		while(iter.hasNext()){
			News vo = iter.next();
			System.out.println(vo);
		}
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

範例:取得訪問量大於100的信息

package org.lks.test;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.News;

public class CriteriaDemoC {

	public static void main(String[] args) {
		Criteria criteria = HibernateSessionFactory.getSession().createCriteria(News.class);
		criteria.add(Restrictions.gt("nvisits", 100));
		List<News> all = criteria.list();
		Iterator<News> iter = all.iterator();
		while(iter.hasNext()){
			News vo = iter.next();
			System.out.println(vo);
		}
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

在整個Criteria操作之中,如果要說最有用處的操作只有一個:IN()操作,因爲這個接口的IN操作可以直接將要查詢的數據以Collection形式保存。
範例:使用IN查詢

package org.lks.test;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.News;

public class CriteriaDemoD {

	public static void main(String[] args) {
		Set<Integer> ids = new HashSet<Integer>();
		ids.add(4);
		ids.add(6);
		ids.add(7);
		Criteria criteria = HibernateSessionFactory.getSession().createCriteria(News.class);
		criteria.add(Restrictions.in("nid", ids));
		List<News> all = criteria.list();
		Iterator<News> iter = all.iterator();
		while(iter.hasNext()){
			News vo = iter.next();
			System.out.println(vo);
		}
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

範例:模糊查詢

package org.lks.test;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.News;

public class CriteriaDemoD {

	public static void main(String[] args) {
		Criteria criteria = HibernateSessionFactory.getSession().createCriteria(News.class);
		criteria.add(Restrictions.like("ntitle", "%%"));
		List<News> all = criteria.list();
		Iterator<News> iter = all.iterator();
		while(iter.hasNext()){
			News vo = iter.next();
			System.out.println(vo);
		}
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

使用以上方法進行模糊查詢需要注意模糊查詢列要爲字符串類型,否則與使用等號無區別。
範例:設置多個條件(and()or()

package org.lks.test;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.News;

public class CriteriaDemoD {

	public static void main(String[] args) {
		Criteria criteria = HibernateSessionFactory.getSession().createCriteria(News.class);
		criteria.add(Restrictions.and(Restrictions.gt("nvisits", 2000), Restrictions.eq("nitem", "笨蛋")));
		List<News> all = criteria.list();
		Iterator<News> iter = all.iterator();
		while(iter.hasNext()){
			News vo = iter.next();
			System.out.println(vo);
		}
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

在使用Criteria接口操作的時候還可以設置排序,裏面提供了排序的方式:public Criteria addOrder(Order order)
(1)升序排列:public static Order asc(String propertyName)
(2)降序排列:public static Order desc(String propertyName)
範例:排序

package org.lks.test;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.News;

public class CriteriaDemoD {

	public static void main(String[] args) {
		Criteria criteria = HibernateSessionFactory.getSession().createCriteria(News.class);
		criteria.addOrder(Order.desc("nid"));
		List<News> all = criteria.list();
		Iterator<News> iter = all.iterator();
		while(iter.hasNext()){
			News vo = iter.next();
			System.out.println(vo);
		}
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

在Criteria接口裏面也支持分組統計查詢,但是這個查詢需要使用此方法支持:
(1)分組統計操作:public Criteria setProjection(Projection projection)
如果要設置條件則應該使用org.hibernate.criterion.Projections實現統計,有如下的方法:
(1)COUNT(*)public static Projection rowCount()
(2)COUNT(字段)public static CountProjection count(String propertyName)
(3)COUNT(DISTINCT 字段):public static CountProjection countDistinct(String propertyName)
(4)AVG()public static AggregateProjection avg(String propertyName)
(5)SUM()public static AggregateProjection sum(String propertyName)
(6)MAX()public static AggregateProjection max(String propertyName)
(7)MIN()public static AggregateProjection min(String propertyName)
(8)設置分組字段:public static PropertyProjection groupProperty(String propertyName)
這些操作都應該是一起查詢出來的,這個時候還需要另外一個類的支持:org.hibernate.criterion.ProjectionList
(1)取得PeojectionList:public static ProjectionList projectionList()
而取得了ProjectionList之後就可以繼續增加多個條件了:public ProjectionList add(Projection projection)
範例:實現信息統計

package org.lks.test;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.News;

public class CriteriaDemoD {

	public static void main(String[] args) {
		Criteria criteria = HibernateSessionFactory.getSession().createCriteria(News.class);
		ProjectionList list = Projections.projectionList();
		list.add(Projections.rowCount());
		list.add(Projections.avg("nvisits"));
		list.add(Projections.groupProperty("ntitle"));
		list.add(Projections.max("nid"));
		criteria.setProjection(list);
		List<Object[]> all = criteria.list();
		Iterator<Object[]> iter = all.iterator();
		while(iter.hasNext()){
			System.out.println(Arrays.toString(iter.next()));
		}
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

還是使用Query+HQL實現數據的分組統計比較簡單,這個操作作爲技術點了解即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章