Hibernate之HQL

什么是HQL?

HQL是Hibernate Query Language的缩写,提供更加丰富灵活、更为强大的查询能力;HQL更接近SQL语句查询语法。

HQL与SQL有何不同:

  1.HQL

  • 对查询条件进行了面向对象封装,符合编程人员的思维方式,格式:from + 类名 + 类对象 + where + 对象的属性

  • 区分大小写,关键字不区分大小写 

  • 从下标0开始计算位置(hibernate5之后不支持)

  • 支持命名参数

  2.SQL

  • sql是面向数据库表查询,格式:from + 表名 + where + 表中字段

  • 不区分大小写

  • 从顺序1开始计算位置

  • 不支持:命名参数

 处理返回的结果集

  • 单个对象

  • 多个列段

  1. object【】
  2. 对象(多个列段、全部)
  • Map

这里写了一个JUnit测试类来测试这些效果

注意:测试类中需要设置session,transaction属性,然后就可以在类中写方法论

    1.  单个对象
     select没有逗号

  如果是单个列段的话,就直接可以用String接收对象,这样就避免一些麻烦

/**
     * 返回单个列段,用字符串就可以接受
     */
    @Test
    public void testList2() {
        Query query = session.createQuery("select b.bookName as ss from Book b");
        List<String> list = query.list();
        for (String b : list) {
            System.out.println(b);
        }
    }

效果:

  2.1 Object[]

    b.bookId, b.bookName...

  如果有两个或者两个以上的列段可以用数组来接收

/**
     * 查两个列段及以上,默认返回的是Object【】
     */
    @Test
    public void testList3() {
        Query query = session.createQuery("select b.bookId,b.bookName as ss from Book b");
        List<Object[]> list = query.list();
        for (Object[] b : list) {
            System.out.println(Arrays.toString(b));
        }
    }

效果:

  2.2 book对象

  其实两个以上也可以用对象来接收

/**
     * 查两个列段及以上,也可返回对象,前提是有对应的构造函数
     */
    @Test
    public void testList5() {
        Query query = session.createQuery("select new Book(b.bookId,b.bookName) from Book b");
        List<Book> list = query.list();
        for (Book b : list) {
            System.out.println(b);
        }
    }

效果:

  2.2.1 也是用对象来接收 

/**
     * 返回对象(多个)
     */
    @Test
    public void testList1() {
        Query query = session.createQuery("from Book");
        List<Book> list = query.list();
        for (Book b : list) {
            System.out.println(b);
        }
    }

  效果:

  

  3.Map

    new Map(b.bookId as bid, b.bookName as bname)

/**
     * 注意map是函数,所以不区分大小写,返回的是map集合
     */
    @Test
    public void testList4() {
        Query query = session.createQuery("select new mAp(b.bookId,b.bookName) from Book b");
        List<Map> list = query.list();
        for (Map b : list) {
            System.out.println(b);
        }
    }

 效果:

HQL中使用占位符

  • 占位符从下标0开始计算位置

    hibernate5之后不再支持占位符

  • 命名参数的使用
/**
     * HQL语句支持占位符
     */
    @Test
    public void testList6() {
//        Query query = session.createQuery("from Book where bookId = :bookId");
//        query.setParameter("bookId", 1);
//        Book b = (Book) query.getSingleResult();
//        System.out.println(b);
        
        Query query = session.createQuery("from Book where bookId in (:bookIds)");
        query.setParameterList("bookIds", new Integer[] {1,2,4});
//        List<Integer> params = new ArrayList<Integer>();
//        params.add(1);
//        params.add(2);
//        params.add(4);
//        query.setParameterList("bookIds", params);
        List<Book> list = query.list();
        for (Book b : list) {
            System.out.println(b);
        }
    }

命名参数的用法就是:

 Query query = session.createQuery("from Book where bookId in (:bookIds)");
        query.setParameterList("bookIds", new Integer[] {1,2,4});

连接查询

/**
     * HQL支持连接查询
     */
    @Test
    public void testList7() {
        Query query = session.createQuery("select o.orderNo,oi.quantity from Order o,OrderItem oi where o = oi.order");
        List<Object[]> list = query.list();
        for (Object[] b : list) {
            System.out.println(Arrays.toString(b));
        }
    }

聚合函数

  • sum    总计

  • avg    平均值

  • max    最大

  • min    最小

  • count  总数

/**
     * HQL支持聚合函数
     */
    @Test
    public void testList8() {
        Query query = session.createQuery("select count(*) from Book");
        Long singleResult = (Long) query.getSingleResult();
        System.out.println(singleResult);
    }

HQL分页

/**
     * HQL分页
     */
    @Test
    public void testList9() {
        Query query = session.createQuery("from Book");
        query.setFirstResult(2);
        query.setMaxResults(3);
        List<Book> list = query.list();
        for (Book b : list) {
            System.out.println(b);
        }
    }

使用HQL实现通用查询

BaseDao类

这就是通用的实体查询类

package com.ht.five.Dao;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.hibernate.Query;
import org.hibernate.Session;
import com.ht.five.Util.PageBean;

/**
 * 通用查询类
 * @author Administrator
 *
 */
public class BaseDao {
    /**
     * @param map 将要设置的阐述用Map的形式来传递
     * @param query 查询对象
     */
    public void setParam(Map<String, Object> map, Query query) {
        if(map != null && map.size() > 0) {
            Object value = null;
            Set<Entry<String, Object>> entries = map.entrySet();
            for (Entry<String, Object> entry : entries) {
                value = entry.getValue();
                //判断类型,根据类型来设置命名参数的值
                if(value instanceof Object[]) {
                    query.setParameterList(entry.getKey(), (Object[])value);
                }else if(value instanceof Collection) {
                    query.setParameterList(entry.getKey(), (Collection)value);
                }else {
                    query.setParameter(entry.getKey(), value);
                }
            }
        }
    }
    /**
     * 传入hql语句 ,返回该语句所查到的总行数
     * @param hql
     * @return
     */
    public String getCountHql(String hql) {
        /**
         * 下面这种做法的原因是请看这两条hql语句:
         * from Book 
         * select * from Book
         * 
         * 所有要想使这个方法同意就是将from这个位置做截断拼接
         */
        //获取到FROM的位置
        int index = hql.toUpperCase().indexOf("FROM");
        //直接从FROM截断,将select count(*) 拼接上就ok了
        return "select count(*)" + hql.substring(index);
    }

    
    /**
     *通用查询方法
     * @param session
     * @param map
     * @param hql
     * @param pageBean
     * @return
     */
    public List executeQuery(Session session, Map<String, Object> map, String hql, PageBean pageBean) {
        List list = null;
        if(pageBean != null && pageBean.isPagination()) {
            //获取该查询的总行数
            String countHql = getCountHql(hql);
            Query countQuery = session.createQuery(countHql);
            //给预定于的hql语句的命名参数赋值
            this.setParam(map, countQuery);
            //将总行数放入PageBean对象
            pageBean.setTotal(countQuery.getSingleResult().toString());
            
            Query query = session.createQuery(hql);
            //给预定于的hql语句的命名参数赋值
            this.setParam(map, query);
            //设置开始位置(下标从0开始)
            query.setFirstResult(pageBean.getStartIndex());
            //这是偏移量,就是一页展示几条数据
            query.setMaxResults(pageBean.getRows());
            list = query.list();
        }
        else {
            //如果不分页 直接查
            Query query = session.createQuery(hql);
            this.setParam(map, query);
            list = query.list();
        }
        return list;
    }
}

BookDao类

继承BaseDao,可以调用它的查询方法为自己用

package com.ht.five.Dao;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.ht.five.Util.PageBean;
import com.ht.five.Util.StringUtils;
import com.ht.four.entity.Book;
import com.ht.two.util.SessionFactoryUtils;

/**
 * 书本Dao方法
 * @author Administrator
 *
 */
public class BookDao extends BaseDao{
    /**
     * 提供查询书籍并分页的方法 该方法基于父类BaseDao实现
     * @param book
     * @param pageBean
     * @return
     */
    public List<Book> list(Book book, PageBean pageBean){
        Session session = SessionFactoryUtils.openSession();
        Transaction transaction = session.beginTransaction();
        
        String bookName = book.getBookName();
        Map<String, Object> map = new HashMap();
        String hql = "from Book where 1=1";
        
        if(StringUtils.isNotBlank(bookName)) {
            hql +=  " and bookName like :bookName";
            map.put("bookName", bookName);
        }
        
        //返回list结果集合
        List<Book> list = super.executeQuery(session, map, hql, pageBean);
        transaction.commit();
        session.close();
        return list;
    }
}

最后在JNUIT测试类中测试

private BookDao bookDao=new BookDao();


/**
     * 测试通用查询
     */
    @Test
    public void testList() {
        Book book = new Book();
        PageBean pageBean = new PageBean();
        pageBean.setPage(2);//根据下标位置来做起始位置(下标从0开始)
        pageBean.setRows(3);//设置每页展示3条数据
        //带条件查询(模糊查询)
        //book.setBookName("%楼%"); 
        List<Book> list = this.bookDao.list(book, pageBean);
        for (Book b : list) {
            System.out.println(b);
        }
    }

今日分享完毕,谢谢观看!

原文地址:https://www.cnblogs.com/huangting/p/11206003.html