Hibernate中可以使用Criteria的特点灵活的组装查询条件
其中,主要有Criteria和DetachedCriteria。两者的区别是一个是离线的,一个是在线。Criteria属于在线,需要由hibernateSession进行创建,而DetachedCriteria,无需hibernateSeession就可以进行创建。所以说我们可以在业务层中根据需求组装一个DetachedCriteria,然后在交给Dao进行查询。
下面主要讲的是DetachedCriteria
一、创建一个DetachedCriteria实例
DetachedCriteria提供了两种的静态方法forClass(Class)和forEntityName(Name)进行DetachedCriteria实例的创建
DetachedCriteria criteria = DetachedCriteria.forClass(UC.class);
DetachedCriteria criteria2 = DetachedCriteria.forEntityName("UC");
二、限制结果集内容
使用DetachedCriteria中的add方法。传入的参数需要实现Criterion接口的一个实例。
我们可以使用org.hibernate.criterion.Restriciton类。它定义了获得某些内置的Criterion类型工厂方法
举个例子:
DetachedCriteria criteria = DetachedCriteria.forClass(UC.class);
criteria.add(Restrictions.like("user_realname", user_realName));
Restrictions包含了基本的Sql的查询条件,例如like between eq(相等)le(小于) get(大于) ne(不相等) and(并且)等等。
需要注意的是在添加条件的时候,默认情况下是and
例如 以下表示的查询条件为user_realname字段的值要like user_realName(传入的参数值) 并且 user_code字段的值要like user_code(传入的参数值)
criteria.add(Restrictions.like("user_realname", user_realName))
.add(Restrictions.like("user_code", user_code));
如果是习惯sql语句,可以使用 Restrictions.sql(sql); 传入sql语句作为查询条件
例如
criteria.add(Restriction.sql("user_code like ? ","2222",Hibernate.STRING);
对于Or和And查询条件,可以通过添加disjunction和conjunciton。这两个添加查询条件方式与DetachedCriteria类似,只不过所有添加的查询限制,全部是以Or和And的方式拼接的。最后,对DetachedCriteria的对象使用add方法,添加刚写的disjunction或conjunciton对象。举例来说
DetachedCriteria criteria = DetachedCriteria.forClass(UC.class);
criteria.add(Restrictions.eq("class_id", class_id));
Disjunction disJunction = Restrictions.disjunction();
disJunction.add(Restrictions.like("user_realname", user_realName));
disJunction.add(Restrictions.ilike("user_code", user_code));
criteria.add(disJunction);
最后的查询条件就是 classid = ? and user_realname = ? or user_code =?
三、多表连接查询
使用DetachedCriteria类
假设,现在有一个表 UC 三个自带安 uc_id(编号), uc_class (班级),uc_user(用户)。后两个为外键,uc_class对应class表的class_id。uc_user对应user表的user_id。另外两个表都只有一个字段。也就是刚提到的class_id和user_id。
现在需要将三个表连接起来,uc表中一个记录,查询条件为class_id 为特定的一个值 并且user_id也为特定的一个值。则可以使用createAlias进行,并且之后设置连接表的查询条件使用的是alias.字段名的方式。
DetachedCriteria criteria = DetachedCriteria.forClass(UC.class);
criteria.createAlias("uc_class", "uClass");
criteria.createAlias("uc_user", "uUser");
criteria.add(Restrictions.eq("uClass.class_id", "213"));
criteria.add(Restrictions.eq("uUser.user_id", "3123"));
如果还有一个表需要进行连接,也是按照同样的道理。比如,class表中还有一个字段class_course对应course表中course_id。则查询uc表中一个记录,查询条件为course的名字为一个特定的值,可以如下。
DetachedCriteria criteria = DetachedCriteria.forClass(UC.class);
criteria.createAlias("uc_class", "uClass");
criteria.createAlias("uc_class.class_course", "cCourse");
criteria.add(Restrictions.eq("cCourse.course_id", "3123"));
四、结果集排序
使用org.hibernate.criterion.Order进行查询结果的排序。使用DetachedCritera的addOrder方法,传入的参数如下形式addOrder(Order.asc("字段名"))、addOrder(Order.desc("字段名"))
五、投影(Projections)、聚合(aggregation)和分组(grouping)
org.hibernate.criterion.Projections是Projection的实例工厂.我们通过调用setProjection()应用投影到一个查询。
//设置投影,列数
criteria .setProjection(Projections.rowCount())
//设置多个投影
criteria.setProjection(Projections.projectionList()
.add(Projections.rowCount()).add(Projections.max("字段名"))
)
分组,两种方式,
第一种
使用setProjection()来设置分组的字段。
使用Projections.alias()来设置分组的别名,方便其他地方进行已用。
使用Projection.groupProperty来设置分组()
Projections.groupProperty
DetachedCriteria criteria = DetachedCriteria.forClass(UC.class);
criteria.setProjection(Projections.alias(Projections.groupProperty("字段名"),"别名"))
.addOrder(Order.asc("别名"));
第二种
使用setProjection()来设置分组的字段。
使用Projection.groupProperty来设置分组()
使用as来设置别名
DetachedCriteria criteria = DetachedCriteria.forClass(UC.class);
criteria.setProjection(Projections.groupProperty("字段名").as("别名"))
.addOrder(Order.asc("别名"));
也可以使用Property.forName()来表示投影:
DetachedCriteria criteria = DetachedCriteria.forClass(UC.class);
criteria.setProjection(Projections.projectionList()
.add(Projections.rowCount().as("别名"))
.add(Property.forName("字段名").max().as("别名"))
.add(Property.forName("字段名").group().as("别名")
)
.addOrder(Order.desc("字段名"))
六、子查询
DetachedCriteria也可以用以表示子查询.条件实例包含子查询可以通过Subqueries或者Property获得.
DetachedCriteria criteria = DetachedCriteria.forClass(UC.class)
.setProjection(Property.forName("uc_id").max());;
DetachedCriteria criteria2 = DetachedCriteria.forClass(Class.class)
criteria2.add(Property.forName(class_id).gt(criteria))
DetachedCriteria criteria = DetachedCriteria.forClass(UC.class)
.setProjection(Property.forName("uc_id"));;
DetachedCriteria criteria2 = DetachedCriteria.forClass(Class.class)
criteria2.add(Subqueries.geAll("uc_id",criteria))
相互关联的子查询也是有可能的:
DetachedCriteria criteria = DetachedCriteria.forClass(Class.class,"class")
.setProjection(Property.forName("num").avg())
.add(Property.forName("class.class_name").eqProperty("classTwo.class_name"));
DetachedCriteria criteria2 = DetachedCriteria.forClass(Class.class,"classTwo")
.add(Property.forName("num).gt(criteria));