Hibernate框架之Criteria查询
首先给大家说说Hibernate检索方式
Hibernate提供了5种检索对象的方式
1.导航对象图检索方式:根据已经加载的对象导航到其他对象
2.OID检索方式:按照对象的OID来检索对象
3.HQL检索方式:使用面向对象的HQL查询语言
4.QBC检索方式:使用QBC(Query By Criteria)API来检索对象,这种API封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口
5.本地SQL检索方式:使用本地数据库的SQL查询语句
Criteria查询是Hibernate提供的另一种查询方式,与HQL基于字符串的查询形式完全不同。Hibernate提供了org.hibernate.Criteria接口,org.hibernate.criterion.Critereion接口和org.hibernate.criterion.Restrictions类等Criteria API,用于支持在运行时动态生成查询语句。
一:条件查询
使用Criteria查询包括以下步骤:
1.使用Session接口的createCriteria()方法创建Criteria对象
2.使用Restrictions类提供的静态方法设置查询条件,这些静态方法返回Criterion对象,一个Criterion对象代表一个查询条件。Criteria借口的add()方法用来添加查询条件。
3.使用Criteria接口的list()方法执行查询语句,list()方法返回java.util.List类型的结果,List集合中的每个元素都是持久化对象。
实例一:使用Criteria查询所有的部门
Session session; Transaction tx; //单元测试前走 @Before public void Before(){ session= HibernateUtil.currentSession(); tx= session.beginTransaction(); } //单元测试后走 @After public void After(){ tx.commit(); HibernateUtil.closeSession(); } @SuppressWarnings("unchecked") @Test //使用Criteria查询所有的部门名称 public void TestOne(){ Criteria criteria = session.createCriteria(Dept.class); List<Dept> list = criteria.list(); for (Dept dept : list) { System.out.println(dept.getDeptname()); } }
实例二:查询部门表为"财务部2"的部门 --Restrictions.between()
public void TestThree(){ List<Dept> list=session.createCriteria(Dept.class).add(Restrictions.eq("deptname", "财务部2")).list(); for (Dept dept : list) { System.out.println(dept.getDeptname()); } }
实例三:查询部门表的deptname为"财务部2"和"财务部"的名称(链式编程风格) --Restrictions.in()
@Test //查询Dept的deptname为财务部2和财务部的名称(链式编程风格) public void TestFour(){ List jobList=new ArrayList<String>();//定义一个数组 jobList.add("财务部"); jobList.add("财务部2"); List<Dept> list=session.createCriteria(Dept.class).add(Restrictions.in("deptname", jobList)).list(); for (Dept dept : list) { System.out.println(dept.getDeptname()); } }
实例四:查询Empinfo表的ehomezipcode(薪资)在500到100000 --Restrictions.between()
@Test //查询Empinfo的ehomezipcode在500到100000 public void TestFive(){ List<Empinfo> list=session.createCriteria(Empinfo.class).add(Restrictions.between("ehomezipcode", 500, 100000)).list(); for (Empinfo empinfo : list) { System.out.println(empinfo.getEname()); } }
实例五:查询部门表中名字有"总"子的员工 --like() ilike()
@Test //查询Empinfo的ename在中有 总 public void TestSix(){ //like 字符串模式匹配 //ilike 字符串模式匹配 同时忽略大小写 List<Empinfo> list=session.createCriteria(Empinfo.class).add(Restrictions.like("ename", "%总%")).list(); for (Empinfo empinfo : list) { System.out.println(empinfo.getEname()); } }
MatchMode类的四种模式:
MatchMode.START:字符串在最前面的位置.相当于"like 'key%'"
MatchMode.END:字符串在最后面的位置.相当于"like '%key'"
MatchMode.ANYWHERE:字符串在中间匹配.相当于"like '%key%'"
MatchMode.EXACT:字符串精确匹配.相当于"like 'key'"
实例六:查询Empinfo的ename在中"张总"或"王总" --Restrictions.or()
@Test //查询Empinfo的ename在中张总或王总 public void TestSeven(){ List<Empinfo> list=session.createCriteria(Empinfo.class).add(Restrictions.or(Restrictions.eq("ename", "张总"), Restrictions.eq("ename", "王总"))).list(); for (Empinfo empinfo : list) { System.out.println(empinfo.getEname()); } }
实例七:查询没有员工的部门 --Restrictions.isEmpty()
@Test //查询没有员工的部门 public void TestEight(){ List<Dept> list=session.createCriteria(Dept.class) .add(Restrictions.isEmpty("emps")) .list(); for (Dept dept : list) { System.out.println(dept.getDeptname()); } }
二:动态查询 --根据判断用户给的条件查询
实例一:Empinfo表中查询条件可为:
1.薪资大于8000
2.街道是"北京大街"
3.城市为"北京"
@Test public void TestNice(){ Criteria criteria = session.createCriteria(Empinfo.class); //00.构建出一个和page对应的条件类,依次判定条件是否为空 Empinfo empinfo=new Empinfo(); empinfo.setEhomecity("北京"); empinfo.setEhomestreet("北京大街"); empinfo.setEhomezipcode(8000); //1.2判定之后,动态拼接检索条件 if (empinfo.getEhomecity()!=null) { //用户填写了城市作为检索条件 criteria.add(Restrictions.eq("ehomecity", empinfo.getEhomecity())); } if(empinfo.getEhomeprovince()!=null){ //用户填写薪资作为筛选条件 criteria.add(Restrictions.gt("ehomeprovince", empinfo.getEhomeprovince())); } if (empinfo.getEhomestreet()!=null) { //用户填写街道作为筛选条件 criteria.add(Restrictions.eq("ehomestreet", empinfo.getEhomestreet())); } List<Empinfo> list = criteria.list(); for (Empinfo emp : list) { System.out.println(emp.getEname()); } }
三:排序查询
HQL使用order by 字句对查询结果排序,Criteria查询使用org.hibernate.criterion.Order类对查询结果排序
升序:addOrder(Order.asc())
降序:addOrder(Order.desc())
实例一:查询Empinfo表按工资升序 --addOrder(Order.asc())
@Test // 查询Empinfo按工资升序 public void TestOne() { List<Empinfo> list = session.createCriteria(Empinfo.class) .addOrder(Order.asc("ehomezipcode")).list(); for (Empinfo empinfo : list) { System.out.println(empinfo.getEhomezipcode()); } }
四:分页查询
Criteria接口提供了设置分页的方法
setFirstResult(int firstResult):设置从哪一个对象开始查询,参数firstResult是个对象在查询结果中的位置,位置的起始值是0
setMaxResult(int maxResult):设置一次最多查询出的对象个数
实例一:分页查询按工资升序后的Empinfo表
@Test // 分页查询Empinfo表 public void TestTwo() { List<Empinfo> list = session.createCriteria(Empinfo.class) .addOrder(Order.asc("ehomezipcode")) .setFirstResult(0) .setMaxResults(2).list(); for (Empinfo empinfo : list) { System.out.println(empinfo.getEhomezipcode()); } }
五:DetachedCriteria
DetachedCriteria和Criteria功能类似,它实现了CriteriaSpecification接口
Criteria是由Session对象创建的
DetachedCriteria创建时不需要Session对象
使用DetachedCriteria来构造查询条件
可以把DetachedCriteria作为方法参数传递给业务层
实例一:查询财务部的员工
@SuppressWarnings("unchecked") @Test public void TestSenven() { DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Emp.class,"e") .createAlias("e.dept", "d") .add(Restrictions.eq("d.deptname", "财务部")); List<Emp> list = detachedCriteria.getExecutableCriteria(session).list(); for (Emp emp : list) { System.out.println(emp.getEmpname()); } }
六:查询唯一对象 --uniqueResult()
uniqueResult()方法用于查询唯一对象。需要注意,必须明确知道查询结果中只有一个对象,才可以直接使用uniqueResult()方法。
实例一:查询Emp表总记录数
@Test // 查询Emp表总记录数 public void TestThree2() { Integer result =(Integer) session.createCriteria(Emp.class) .setProjection(Projections.count("empno")).uniqueResult(); System.out.println(result); }
七:连接查询
1.内连接
01.使用createCriteria()
实例一:查询财务部的姓名中包括“总”的员工
@Test // 查询财务部的姓名中包括“总”的员工 public void TestFour() { List<Emp> list = session.createCriteria(Emp.class) .add(Restrictions.ilike("empname", "总", MatchMode.ANYWHERE)) .createCriteria("dept") .add(Restrictions.eq("deptname", "财务部").ignoreCase()).list(); for (Emp emp : list) { System.out.println(emp.getEmpname()); } }
02.使用createAlias()
实例一:查询财务部的姓名中包括“总”的员工
@Test // 查询财务部的姓名中包括“总”的员工 public void TestFive() { List<Emp> list = session.createCriteria(Emp.class, "e") .createAlias("dept", "d") .add(Restrictions.ilike("e.empname", "总", MatchMode.ANYWHERE)) .add(Restrictions.eq("d.deptname", "财务部").ignoreCase()).list(); for (Emp emp : list) { System.out.println(emp.getEmpname()); } }
2.迫切左连接 --setFetchMode()
实例一:查询部门为“财务部”的员工个数
@Test // 查询部门为“财务部”的员工个数 public void TestSix() { List<Dept> list = session.createCriteria(Dept.class, "d") .setFetchMode("emps", FetchMode.JOIN) .add(Restrictions.eq("deptname", "财务部")) .list(); //使用Set接口的实现类HashSet来过滤重复的数据(HashSet中不会存储相同的值) HashSet<Dept> set=new HashSet<Dept>(list); for (Dept dept : set) { System.out.println(dept.getDeptname()+","+dept.getEmps().size()); } }