Hibernate中QBC查询
QBC 查询
QBC,即 Query By Criteria,它是 Hibernate 提供的另一种查询方式,使用 HQL 查询需要写 hql 语句,但使用 QBC 查询不需要写语句,直接使用方法实现
QBC 操作的是实体类和属性,使用 Criteria 对象实现 QBC 查询
基本查询:
以客户和联系人为例(一对多),下同:
1、查询所有记录
(1)创建 Criteria 对象
(2)调用 Criteria 对象的方法得到结果
/* * (1) 创建 Criteria 对象 * 调用 session 的 createCriteria() 方法,参数是实体类的 class,返回值是 Criteria 类型,创建以接收 */ Criteria criteria=session.createCriteria(Customer.class); /* * (2) 调用方法得到结果 * 调用 criteria 的 list() 方法,返回值是 List 类型,创建以接收 */ List<Customer> list=criteria.list();
条件查询:
(1)多条件查询
/* * (1) 创建 Criteria 对象 * 调用 session 的 createCriteria() 方法,参数是实体类的 class,返回值是 Criteria 类型,创建以接收 */ Criteria criteria = session.createCriteria(Customer.class); /* * (2) 使用 criteria 的方法设置条件 * 调用 criteria 的 add() 方法,设置条件值,类似于 HQL 中 where cid=? and custName=? */ criteria.add(Restrictions.eq("cid",1)); criteria.add(Restrictions.eq("custName","百度")); /* * (3) 调用方法得到结果 * 调用 criteria 的 list() 方法,返回值是 List 类型,创建以接收 */ List<Customer> list = criteria.list();
(2)模糊查询
/* * (1) 创建 Criteria 对象 * 调用 session 的 createCriteria() 方法,参数是实体类的 class,返回值是 Criteria 类型,创建以接收 */ Criteria criteria = session.createCriteria(Customer.class); /* * (2) 使用 criteria 的方法设置条件 * 调用 criteria 的 add() 方法,设置条件值,类似于 HQL 中 where custName like ? */ criteria.add(Restrictions.like("custName","%度%")); /* * (3) 调用方法得到结果 * 调用 criteria 的 list() 方法,返回值是 List 类型,创建以接收 */ List<Customer> list = criteria.list();
排序查询
/* * (1) 创建 Criteria 对象 * 调用 session 的 createCriteria() 方法,参数是实体类的 class,返回值是 Criteria 类型,创建以接收 */ Criteria criteria = session.createCriteria(Customer.class); /* * (2) 设置对哪个属性进行排序以及排序规则 */ criteria.addOrder(Order.asc("cid")); /* * (3) 调用方法得到结果 * 调用 criteria 的 list() 方法,返回值是 List 类型,创建以接收 */ List<Customer> list = criteria.list();
分页查询
/* * (1) 创建 Criteria 对象 * 调用 session 的 createCriteria() 方法,参数是实体类的 class,返回值是 Criteria 类型,创建以接收 */ Criteria criteria = session.createCriteria(Customer.class); /* * (2) 设置分页数据 * 开始位置和每页的记录数 */ criteria.setFirstResult(0); criteria.setMaxResults(10); /* * (3) 调用方法得到结果 * 调用 criteria 的 list() 方法,返回值是 List 类 型,创建以接收 */ List<Customer> list = criteria.list(); /* * 开始位置计算公式:(当前页 - 1) * 每页记录数 */
统计查询
/* * (1) 创建 Criteria 对象 * 调用 session 的 createCriteria() 方法,参数是实体类的 class,返回值是 Criteria 类型,创建以接收 */ Criteria criteria = session.createCriteria(Customer.class); /* * (2) 设置操作 */ criteria.setProjection(Projections.rowCount()); /* * (3) 调用方法得到结果 * 调用 criteria 的 uniqueResult() 方法,返回值是Object 类型,创建以接收 */ Object obj = criteria.uniqueResult(); /* * 注意:不能直接把 obj 转成 int 类型,需要先转成Long 类型: * Long val=(Long) obj; * int valx=val.intValue(); */
离线查询
也称离线条件查询,可以脱离 Session 而对条件进行封装
应用场景:
Servlet 调用 Service,Service 调用 DAO
一般情况下,参数往往是从 Web 层传到业务层,进而传到 DAO层,最后在 DAO 层中拼接 SQL 完成查询
有了离线查询后,就可以直接在 Web 层将数据封装好,传到业务层,进而传到 DAO 层完成查询
使用 DetachedCriteria 对象实现离线条件查询
/* * (1) 创建 DetachedCriteria 对象(离线对象) * 调用 DetachedCriteria 的 forClass() 静态方法,参数是实体类的 class,返回值是 DetachedCriteria类型,创建以接收 */ DetachedCriteria detachedCriteria=DetachedCriteria.forClass(Customer.class); /* * (2) 最终执行时才需要 Session * 调用 detachedCriteria 的 getExecutableCriteria()方法,返回值是 Criteria 类型,创建以接收 */ Criteria criteria=detachedCriteria.getExecutableCriteria(session); /* * (3) 调用方法得到结果 * 调用 criteria 的 list() 方法,返回值是 List 类型,创建以接收 */ List<Customer> list=criteria.list();
连表查询(子查询):
//中心采购看所有,自行采购看本部门 String deptid = demand.get("deptId"); if(StringUtils.hasText(deptid)) { criteria.createAlias("appUser", "u"); criteria.add(Expression.eq("u.dept.id", Long.parseLong(deptid))); //三表:采购表,user表,dept表。appUser和dept是配的关系。 String series = demand.get("samples.labSeries"); if (org.springframework.util.StringUtils.hasText(series)) { criteria.add(Expression.sqlRestriction(" id in (select suit_Id from samples where lab_Series='" + series + "')")); } }
实体类结构:
Session session = sc.getCurrentSession(); Transaction transaction = session.beginTransaction(); Criteria criteria = session.createCriteria(Pass.class); criteria =criteria.createAlias("user","u"); criteria =criteria.add(Property.forName("u.id").eq(101)); List<Pass> list = criteria.list(); System.out.println(list); transaction.commit();
输出的最终的sql语句:
左外连接:
/* * 一对多双向关联-左外连接-QBC */ @Test public void testLeft() { try { session.beginTransaction(); List<Forum> list = session.createCriteria(Forum.class) .createCriteria("forumPosts", JoinType.LEFT_OUTER_JOIN) .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY) .list(); for (Forum forum : list) { System.out.println(forum.getName()); } session.getTransaction().commit(); } catch (Exception e) { session.getTransaction().rollback(); e.printStackTrace(); } }