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实现数据的分组统计比较简单,这个操作作为技术点了解即可。

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