Criteria查询是Hibernate提供的另一种查询方式,与HQL基于字符串的查询形式完全不同。Hibernate提供了org.Hibernate.Criteria接口、org.hibernate.criterion.Criterion接口和org.hibernate.criterion .Restrictions类等Criteria API,用于支持在运行时动态生成查询语句。
1. 条件查询
使用Criteria查询包括以下步骤:
(1)使用Session接口的createCriteria()方法创建Criteria对象。
(2)使用Restrictions类提供的静态方法设置查询条件,这些静态方法返回Criterion对象,一个Criterion对象代表一个查询条件。Criteria接口的add()方法用来添加查询条件。
(3)使用Criteria接口的list()方法执行查询语句,list()方法返回java.util.List类型的结果,List集合中的每个元素都是持久化对象。
接下来通过示例来说明。
案例1 查询男学生package com.obtk.test;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import com.obtk.entitys.StudentEntity;
import com.obtk.utils.HiberUtil;
public class CriteraTest1 {
public static void main(String[] args) {
Session session=null;
try {
session=HiberUtil.getSession();
Criteria cri=session.createCriteria(StudentEntity.class);
cri=cri.add(Restrictions.eq("gender", "男"));
List<StudentEntity> stuList=cri.list();
for(StudentEntity stu : stuList){
System.out.println(stu.getStuId()+"\t"+stu.getStuName()+"\t"+stu.getGender());
}
} catch (HibernateException e) {
e.printStackTrace();
}finally{
HiberUtil.closeSession();
}
}
}
案例2 多条件查询,链式编程
package com.obtk.test;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import com.obtk.entitys.StudentEntity;
import com.obtk.utils.HiberUtil;
public class CriteraTest2 {
public static void main(String[] args) {
Session session=null;
try {
session=HiberUtil.getSession();
//添加条件,链式编程
Criteria cri=session.createCriteria(StudentEntity.class)
.add(Restrictions.eq("gender", "男"))
.add(Restrictions.ge("age", 20))
.add(Restrictions.le("age", 26))
.add(Restrictions.isNotNull("dept"));
List<StudentEntity> stuList=cri.list();
for(StudentEntity stu : stuList){
System.out.println(stu.getStuId()+"\t"+stu.getStuName()+"\t"+stu.getGender());
}
} catch (HibernateException e) {
e.printStackTrace();
}finally{
HiberUtil.closeSession();
}
}
}
package com.obtk.test;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import com.obtk.entitys.StudentEntity;
import com.obtk.utils.HiberUtil;
public class CriteraTest3 {
public static void main(String[] args) {
Session session=null;
try {
session=HiberUtil.getSession();
//范围查询
//String[] theValues={"男","妖"};
//添加条件,链式编程
Criteria cri=session.createCriteria(StudentEntity.class)
//.add(Restrictions.in("gender", theValues));
.add(Restrictions.between("age", 20, 26));
List<StudentEntity> stuList=cri.list();
for(StudentEntity stu : stuList){
System.out.println(stu.getStuId()+"\t"+stu.getStuName()
+"\t"+stu.getGender()+"\t"+stu.getAge());
}
} catch (HibernateException e) {
e.printStackTrace();
}finally{
HiberUtil.closeSession();
}
}
}
案例4 模糊查询
package com.obtk.test;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import com.obtk.entitys.StudentEntity;
import com.obtk.utils.HiberUtil;
public class CriteraTest4 {
public static void main(String[] args) {
Session session=null;
try {
session=HiberUtil.getSession();
//模糊查询
Criteria cri=session.createCriteria(StudentEntity.class)
.add(Restrictions.like("stuName", "发", MatchMode.END));
List<StudentEntity> stuList=cri.list();
for(StudentEntity stu : stuList){
System.out.println(stu.getStuId()+"\t"+stu.getStuName()
+"\t"+stu.getGender()+"\t"+stu.getAge());
}
} catch (HibernateException e) {
e.printStackTrace();
}finally{
HiberUtil.closeSession();
}
}
}
案例5 非空查询
package com.obtk.test;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import com.obtk.entitys.DeptEntity;
import com.obtk.entitys.StudentEntity;
import com.obtk.utils.HiberUtil;
public class CriteraTest5 {
public static void main(String[] args) {
Session session=null;
try {
session=HiberUtil.getSession();
//非空查询
Criteria cri=session.createCriteria(DeptEntity.class)
.add(Restrictions.isNotEmpty("stuList"));
List<DeptEntity> stuList=cri.list();
for(DeptEntity stu : stuList){
System.out.println(stu.getDeptId()+"\t"+stu.getDepartName());
}
} catch (HibernateException e) {
e.printStackTrace();
}finally{
HiberUtil.closeSession();
}
}
}
2. 动态条件查询
在HQL语句里面我们介绍了使用HQL实现动态查询,下面介绍使用Criteria实现动态查询。请自行对比二者的使用的优缺点。
==========条件实体类ConditionEnity=========================
package com.obtk.entitys;
public class ConditionEnity {
private String stuName;
private String gender;
private Integer minAge;
private Integer maxAge;
public ConditionEnity() {
}
public ConditionEnity(String stuName, String gender, Integer minAge,
Integer maxAge) {
super();
this.stuName = stuName;
this.gender = gender;
this.minAge = minAge;
this.maxAge = maxAge;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Integer getMinAge() {
return minAge;
}
public void setMinAge(Integer minAge) {
this.minAge = minAge;
}
public Integer getMaxAge() {
return maxAge;
}
public void setMaxAge(Integer maxAge) {
this.maxAge = maxAge;
}
}
================ConditionQuery.java====================
package com.obtk.test;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import com.obtk.entitys.ConditionEnity;
import com.obtk.entitys.StudentEntity;
import com.obtk.utils.HiberUtil;
public class ConditionQuery {
public static void queryByCon(ConditionEnity con){
Session session=null;
try {
session=HiberUtil.getSession();
Criteria cri=session.createCriteria(StudentEntity.class);
if(con.getStuName()!=null){
cri.add(Restrictions.like("stuName", con.getStuName(),MatchMode.ANYWHERE));
}
if(con.getGender()!=null){
cri.add(Restrictions.eq("gender",con.getGender()));
}
if(con.getMinAge()!=null){
cri.add(Restrictions.ge("age",con.getMinAge()));
}
if(con.getMaxAge()!=null){
cri.add(Restrictions.le("age",con.getMaxAge()));
}
List<StudentEntity> stuList=cri.list();
for(StudentEntity stu : stuList){
System.out.println(stu.getStuName()+"\t"+stu.getGender()+"\t"+stu.getAge());
}
} catch (HibernateException e) {
e.printStackTrace();
}finally{
HiberUtil.closeSession();
}
}
public static void main(String[] args) {
//是在servlet和action里面完成
ConditionEnity con=new ConditionEnity("张", "男", null, 26);
queryByCon(con);
}
}
3 排序,唯一查询,分页查询
案例1 唯一查询
package com.obtk.test;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import com.obtk.entitys.ConditionEnity;
import com.obtk.entitys.StudentEntity;
import com.obtk.utils.HiberUtil;
public class CountTest {
public static void main(String[] args) {
Session session=null;
try {
session=HiberUtil.getSession();
Criteria cri=session.createCriteria(StudentEntity.class);
//查多少行数据
cri.setProjection(Projections.count("stuId"));
Integer count=(Integer)cri.uniqueResult();
System.out.println("总条数:"+count);
} catch (HibernateException e) {
e.printStackTrace();
}finally{
HiberUtil.closeSession();
}
}
}
案例2 排序及分页
package com.obtk.test;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import com.obtk.entitys.StudentEntity;
import com.obtk.utils.HiberUtil;
public class PageQuery {
static int getTotalRows(){
Session session=null;
Integer count=0;
try {
session=HiberUtil.getSession();
Criteria cri=session.createCriteria(StudentEntity.class);
//查多少行数据
cri.setProjection(Projections.count("stuId"));
count=(Integer)cri.uniqueResult();
} catch (HibernateException e) {
e.printStackTrace();
}finally{
HiberUtil.closeSession();
}
return count;
}
static void queryPage(Integer pageNo,Integer pageSize){
Session session=null;
try {
session=HiberUtil.getSession();
Criteria cri=session.createCriteria(StudentEntity.class);
cri.addOrder(Order.desc("age")); //排序
cri.setFirstResult((pageNo-1)*pageSize); //设置从哪一条数据开始
cri.setMaxResults(pageSize); //设置每页显示多少条
List<StudentEntity> stuList=cri.list();
System.out.println("总条数:"+getTotalRows());
for(StudentEntity stu : stuList){
System.out.println(stu.getStuId()+"\t"+stu.getStuName()
+"\t"+stu.getGender()+"\t"+stu.getAge());
}
} catch (HibernateException e) {
e.printStackTrace();
}finally{
HiberUtil.closeSession();
}
}
public static void main(String[] args) {
queryPage(2,3);
}
}
4. 连接查询
案例1 内关联
package com.obtk.test;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import com.obtk.entitys.DeptEntity;
import com.obtk.entitys.StudentEntity;
import com.obtk.utils.HiberUtil;
public class JoinTest {
public static void main(String[] args) {
Session session=null;
try {
session=HiberUtil.getSession();
Criteria cri=session.createCriteria(StudentEntity.class,"s")
.createAlias("s.dept", "d")
.add(Restrictions.eq("d.departName", "计算机系"))
.add(Restrictions.like("s.stuName", "张", MatchMode.ANYWHERE));
List<StudentEntity> stuList=cri.list();
for(StudentEntity stu : stuList){
System.out.println(stu.getStuId()+"\t"+stu.getStuName()+"\t"+stu.getGender()
+"\t"+stu.getDept().getDepartName());
}
} catch (HibernateException e) {
e.printStackTrace();
}finally{
HiberUtil.closeSession();
}
}
}
5. 投影及分组查询
案例1 投影
package com.obtk.test;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import com.obtk.entitys.StudentEntity;
import com.obtk.utils.HiberUtil;
public class GroupTest1 {
public static void main(String[] args) {
Session session=null;
try {
session=HiberUtil.getSession();
Criteria cri=session.createCriteria(StudentEntity.class)
.setProjection(Projections.projectionList()
.add(Property.forName("stuName"))
.add(Property.forName("gender")));
List<Object[]> rows=cri.list();
for(Object[] row : rows){
System.out.println(row[0]+"\t"+row[1]);
}
} catch (HibernateException e) {
e.printStackTrace();
}finally{
HiberUtil.closeSession();
}
}
}
案例2 分组
package com.obtk.test;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import com.obtk.entitys.StudentEntity;
import com.obtk.utils.HiberUtil;
public class GroupTest2 {
public static void main(String[] args) {
Session session=null;
try {
session=HiberUtil.getSession();
Criteria cri=session.createCriteria(StudentEntity.class,"s")
.createAlias("s.dept", "d")
.setProjection(Projections.projectionList()
//指明分组的列
.add(Projections.groupProperty("d.departName"))
.add(Projections.min("s.age"))
.add(Projections.avg("s.age"))
.add(Projections.max("s.age"))
);
List<Object[]> rows=cri.list();
for(Object[] row : rows){
System.out.println(row[0]+"\t"+row[1]+"\t"+row[2]+"\t"+row[3]);
}
} catch (HibernateException e) {
e.printStackTrace();
}finally{
HiberUtil.closeSession();
}
}
}
DetachedCriteria类和Criteria接口功能类似,它们分别实现和继承了CriteriaSpecification接口。Criteria与DetachedCriteria均可使用Criterion与Projection设置查询条件,但两者的创建形式不同。
(1)Criteria是由Session对象创建的。
(2)DetachedCriteria创建时不需要Session对象。
Hibernate支持DetachedCriteria这是一个非常有意义的特性。如下应用场景可以考虑使用DetacbedCriteria查询:在常规的Web编程中,有大量的动态条件查询,即用户在网页上自由选择某些条件,程序根据用户的选择条件,动态生成SQL语句,进行查询。针对这种需求,对于分层应用程序来说,Web层需要传递一个查询的条件列表给业务层对象,业务层对象获得这个条件列表之后,依次取出条件,构造查询语句。
这里的难点是条件列表用什么来构造。传统上使用Map,但是Map传递的信息非常有限,只能传递name和value,无法传递究竟要做怎样的条件运算,究竟进行大于、小于,还是like等操作,业务层对象必须确切掌握所有的隐含条件才能判断。因此,一旦隐含条件改变,业务层对象的查询构造算法必须相应修改。但是这种查询条件的改变是隐式约定的,不是程序代码约束的,因此,非常容易出错。
DetachedCriteria可以解决这个问题,即在Web层,程序员使用DetachedCriteria来构造查询条件,然后将DetachedCriteria作为方法调用参数传递给业务层对象。业务层对象获得DetachedCriteria后,可以在Session范围内直接构造Criteria进行查询。到此为止,查询语句的构造完全被搬离到Web层实现,两业务层则与查询条件构造完全解耦。
案例1package com.obtk.test;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import com.obtk.entitys.StudentEntity;
import com.obtk.utils.HiberUtil;
public class DetachTest {
public static void main(String[] args) {
try {
//方便web分层处理,解耦
DetachedCriteria dech=DetachedCriteria.forClass(StudentEntity.class,"s")
.createAlias("s.dept", "d")
.add(Restrictions.like("s.stuName", "张", MatchMode.ANYWHERE))
.add(Restrictions.eq("s.gender", "男"))
.add(Restrictions.eq("d.departName", "计算机系"));
List<StudentEntity> stuList=dech.getExecutableCriteria(HiberUtil.getSession())
.list();
for(StudentEntity stu : stuList){
System.out.println(stu.getStuId()+"\t"+stu.getStuName()+"\t"+stu.getGender()
+"\t"+stu.getDept().getDepartName());
}
} catch (HibernateException e) {
e.printStackTrace();
}finally{
HiberUtil.closeSession();
}
}
}