1. 什么是hql

HQL是Hibernate Query Language的缩写
比如这样一段代码!

package com.chenkang.one.test;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

/**
 * hibernate 中查询案例
 * @author Administrator
 *
 */
public class QueryDemo {
	public static void main(String[] args) {
//		对hibernate.cfg.xml进行建模拿到sessionfactory工厂(两步)
		Configuration configure = new Configuration().configure("/hibernate.cfg.xml");
		SessionFactory sessionFactory = configure.buildSessionFactory();
//		通过工厂获取到session对话(操作数据库)
		Session session = sessionFactory.openSession();
//		直接操作数据库
		List list = session.createQuery("from User").list();
		for (Object object : list) {
			System.out.println(object);
		}
//		关闭资源
		session.close();

	}
}

里面操作数据库就是用的 HQL语句

2. hql和sql区别/异同

HQL                                                				 					                                 	                    SQL

类名/属性 表名/列名
区分大小写,关键字不区分大小写 不区分大小写
别名 别名
?,从下标0开始计算位置(hibernate5之后不支持) ?, 从顺序1开始计算位置
:命名参数 不支持:命名参数
面向对象的查询语言 面向结构查询语言

那么问题来了如果我们想查询单个或者想用分页该怎么写代码…

3.Hql语句的特性

package com.chenkang.five.test;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.query.Query;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.chenkang.four.entity.Book;
import com.chenkang.two.util.SessionFactoryUtils;


public class HqlTest {
	private Session session;
	private Transaction transaction;

	@Before
	public void before() {
		session = SessionFactoryUtils.openSession();
		transaction = session.beginTransaction();
	}

	@After
	public void after() {
		transaction.commit();
		session.close();
	}

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

	/**
	 * 返回单个列段,用字符串就可以接受
	 */
	@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);
		}
	}

	/**
	 * 查两个列段及以上,默认返回的是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));
		}
	}

	/**
	 * 注意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);
		}
	}

	/**
	 * 查两个列段及以上,也可返回对象,前提是有对应的构造函数
	 */
	@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);
		}
	}

我们在实际开发中都是用的返回多个对象的!!

4. hql中使用占位符

/**
	 * 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);
		}
	}

5.连接查询

/**
	 * 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));
		}
	}

6. 聚合函数

聚合函数有 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);
	}

7. hql分页

int page = 2;// 页码:page
int row = 10;// 每页行数:rows
query.setFirstResult((page - 1) * row);// 设置起始记录下标
query.setMaxResults(row);// 设置返回的最大结果集

/**
	 * 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);
		}
	}

8.接下来我们来写能够用到模糊查询和分页的通用查询方法BaseDao:

我们先用原生态的BaseDao来写我们通用的查询方法

public List<Book> list1(Book book,PageBean pageBean) {
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
//		下面代码处理是book实体类条件查询
		String bookName = book.getBookName();
//		sql语句where后面可以直接写true,而hql语句不能写true
		String hql= "from Book where 1=1";
		if(StringUtils.isNotBlank(bookName)) {
			hql +=" and bookName like :bookName";
		}
		Query query = session.createQuery(hql);
		if(StringUtils.isNotBlank(bookName)) {
			query.setParameter("bookName", bookName);
		}
//		处理的是分页
		if(pageBean !=null && pageBean.isPagination()) {
		query.setFirstResult(pageBean.getStartIndex());
		query.setMaxResults(pageBean.getRows());
		}
		List list = query.list();

		transaction.commit();
		session.close();
		return list;

	}

然后运行代码:

	public void testList1() {
		Book book = new Book();
//		book.setBookName("%圣墟%");
		PageBean pageBean = new PageBean();
		pageBean.setPage(2);
		List<Book> list1 = this.bookDao.list1(book, pageBean);
		for (Book b : list1) {
			System.out.println(b);

运行结果:
首先是模糊查询然后就是分页
Hibernate之HQL-LMLPHP
Hibernate之HQL-LMLPHP

接下来我们要自己手写BaseDao的方法来减少代码的开发周期

BaseDao:

package com.chenkang.five.util;import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.mapping.Collection;
import org.hibernate.query.Query;



/**
 * hibernate的通用查询Dao层
 * 思想完全借鉴于sql的BaseDao
 * 	sql = select * from t_mvc_book where bname like '%圣墟%'
 *   countSql = select count(1) from (sql) t;
 *   pageSql = sql limit start,offset
 *
 *   hql:
 *   hql = select * from Book where bookName like :bookName
 *   hql = from Book where bookName like :bookName
 *   思想,将原生的hql语句以from关键字进行截取
 *   countHql = select count(*) from Book where bookName like :bookName
 *   pageSql不需要写因为hibernate已经封装了内置分页接口
 *   getFirstResult
 *   getMaxResult
 *
 * @author Administrator
 *
 */
public class BaseDao {
		/**
		 * 给hibernate中的Query对象中的命名参数列表赋值
		 * @param query
		 * @param map
		 */
	public void setParam(Query query,Map<String, Object> map) {
		if(map != null && map.size()>0) {
			Set<Entry<String, Object>> entrySet = map.entrySet();
			for (Entry<String, Object> entry : entrySet) {
				Object value = entry.getValue();
				if(value instanceof Collection)
					query.setParameter(entry.getKey(), (Collection)value);
				else if (value instanceof Object[])
					query.setParameter(entry.getKey(), (Object[])value);
				else
				query.setParameter(entry.getKey(), value);
			}
		}
	}
	public String getCountHql(String hql) {
		return "select count(*)" + hql.substring(hql.toUpperCase().indexOf("FROM"));

	}
	/**
	 * 通用的hql语句查询
	 * @param session 当前会话
	 * @param hql	带命名的hql语句
	 * @param map	 命名参数对应的值得集合
	 * @param pageBean	 分页实体类
	 * @return
	 */
	public List executeQuery(Session session,String hql,Map<String, Object> map,PageBean pageBean) {
			List list=null;
			Query query = null;
			if(pageBean !=null && pageBean.isPagination()) {
				String countHql = getCountHql(hql);
				Query createQuery = session.createQuery(countHql);
				this.setParam(createQuery, map);
				pageBean.setTotal(createQuery.getSingleResult().toString());

				query = session.createQuery(hql);
				this.setParam(query, map);
				query.setFirstResult(pageBean.getStartIndex());
				query.setMaxResults(pageBean.getRows());
				list=query.list();

			}else {
				query = session.createQuery(hql);
				this.setParam(query, map);
				list = query.list();
			}
		return list;

	}

}

然后写查询方法

public List<Book> list2(Book book,PageBean pageBean) {
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
//		下面代码处理是book实体类条件查询
		String bookName = book.getBookName();
		Map<String, Object> map = new HashMap<String, Object>();
//		sql语句where后面可以直接写true,而hql语句不能写true
		String hql= "from Book where 1=1";
		if(StringUtils.isNotBlank(bookName)) {
			hql +=" and bookName like :bookName";
			map.put("bookName", bookName);
		}

//		处理的是分页

		List list = super.executeQuery(session, hql, map, pageBean);

		transaction.commit();
		session.close();
		return list;

很显然我们减少了一丢丢的代码!!
至于代码的测试和运行我就不说了,跟上面的一样
!!
就简化带查询方法的代码!1

08-09 18:21