Loading

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();
        }
    }

 

posted @ 2022-03-13 22:27  1640808365  阅读(365)  评论(0编辑  收藏  举报