Hibernate hql总结及BaseDao封装

1.hql:Hibernate Query Language(Hibernate查询语言)

作用:方便进行数据库操作

 

2. hql和sql区别

     1.hql是基于实体属性进行查询的;sql是基于表实体进行查询的

     2.hql区分大小写,关键字不区分大小写;sql不区分大小写

     3.hql是面向对象的查询语言;sql是面向结构的查询语言

     4.hql占位符下标从0开始(目前推荐使用:命名参数);sql占位符下标从1开始

 

3.5种处理hql查询返回的结果集

这里以Book类为实例

        /**
	 * 结果处理一:当结果集为集合,查单个也可以通过这种方式,只不过不需要遍历
	 */
	@Test
	public void testList1() {
		String hql = "from Book";
		Query query = session.createQuery(hql);
		List list = query.list();
		for (Book book : list) {
			System.out.println(book);
		}
	}
	
	/**
	 * 结果处理二:当结果集为集合,并且只查询其中一列时
	 */
	@Test
	public void testList2() {
		String hql = "select bookName from Book";
		Query query = session.createQuery(hql);
		List list = query.list();
		for (String bname : list) {
			System.out.println(bname);
		}
	}
	
	/**
	 * 结果处理三:当结果集为集合,并且查询两列及两列以上,使用Object[]
	 */
	@Test
	public void testList3() {
		String hql = "select bookId,bookName from Book";
		Query query = session.createQuery(hql);
		List list = query.list();
		for (Object[] book : list) {
			System.out.println(Arrays.toString(book));
		}
	}
	
	/**
	 * 结果处理四:当结果集为集合,并且查询两列及两列以上,使用hibernate内置函数
	 */
	@Test
	public void testList4() {
		String hql = "select new map(bookId,bookName) from Book";
		Query query = session.createQuery(hql);
		List list = query.list();
		for (Map book : list) {
			System.out.println(book);
		}
	}
	
	/**
	 * 结果处理五:当结果集为集合,并且查询两列及两列以上,使用构造方法进行结果处理,记得提供对应构造器!!
	 */
	@Test
	public void testList5() {
		String hql = "select new Book(bookId,bookName) from Book";
		Query query = session.createQuery(hql);
		List list = query.list();
		for (Book book : list) {
			System.out.println(book);
		}
	}

 

4.hql的命名参数:等同于占位符,推荐使用该方式

        @Test
	public void testList6() {
		//此处的:bookIds相当于占位符,不要漏掉:
		String hql = "from Book where bookId in (:bookIds)";
		Query query = session.createQuery(hql);
		List params = new ArrayList();
		params.add(1);
		params.add(2);
		//为bookIds赋值,也可以使用下标,hql的下标是从0开始
		query.setParameterList("bookIds",params);
		List list = query.list();
		for (Book book : list) {
			System.out.println(book);
		}
	}

 

5.使用hql完成联表查询

        @Test
	public void testList7() {
		String hql = "select o.order_no,oi.product_id from Order o,OrderItem oi where o.order_id = oi.order.order_id";
		//String hql = "select o.order_no,oi.product_id from Order o,OrderItem oi where o = oi.order";
		Query query = session.createQuery(hql);
		List list = query.list();
		for (Object[] obj : list) {
			System.out.println(Arrays.toString(obj));
		}
	}

 

6.hql的聚合函数

   sum
   avg
   max
   min
   count

这里以count示例

        @Test
	public void testList8() {
		String hql = "select count(*) from Book";
		Query query = session.createQuery(hql);
		Object obj = query.getSingleResult();
		System.out.println(obj);
	}

 

7.使用hql完成分页

hql内部是有封装分页的,所以分页不需要我们自己写,只需要提供分页信息就行了

        @Test
	public void testList9() {
		//数据库为mysql
		String hql = "from Book where bookName like :bookName";
		int rows = 3;//每页显示3条记录
		int page = 1;//第一页
		Query query = session.createQuery(hql);
		query.setParameter("bookName", "%红%");//模糊查询
		query.setFirstResult((page-1)*rows);//从第几条数据开始查,索引从0开始
		query.setMaxResults(rows);
		List list = query.list();
		for (Book book : list) {
			System.out.println(book);
		}
	}

 

8.对hql的操作进行封装(BaseDao封装):方便开发,减少冗余代码

示例:带条件的查询分页

        public List list1(Book book,PageBean pageBean){
		Session session = SessionFactoryUtils.getSession();
		Transaction transaction = session.beginTransaction();
		String hql = "from Book where 1=1";
		if (StringUtils.isNotBlank(book.getBookName())) {
			hql += " and book_name like :book_name";
		}
		Query query = session.createQuery(hql);
		if (StringUtils.isNotBlank(book.getBookName())) {
			query.setParameter("book_name", "%"+book.getBookName()+"%");
		}
		if (pageBean != null && pageBean.isPagination()) {
			query.setFirstResult(pageBean.getStartPage());
			query.setMaxResults(pageBean.getTotalPage());
		}
		List list = query.list();
		return list;
	}

注:setParameter方法是BaseDao封装的设置参数方法,所以代码中减少了赋值的代码,这也是BaseDao的一个好处,后面会有代码,这里主要看赋值以外的

从如上代码可以看到,随着查询条件的增加,那么对应的if判断就会很多,因此为了减少代码的冗余,可以对其进行封装

 

BaseDao封装:

package com.study.dao;

import java.util.Collection;
import java.util.List;
import java.util.Map;

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

import com.zking.util.PageBean;

/**
 * BaseDao作用:
 * 	1.特定值赋值
 * 	2.分页
 * 		1.查总记录数
 * 		2.查询某一页纪录
 * @author L
 *
 */
public class BaseDao {
	//1.参数赋值
	public void setParameter(Query query,Map map) {
		if (map == null || map.size() == 0) {
			return;
		}
		
		Object value = null;
		for (Map.Entry entry : map.entrySet()) {
			value = entry.getValue();
			if (value instanceof Collection) {
				query.setParameterList(entry.getKey(), (Collection)value);
			}
			else if (value instanceof Object[]) {
				query.setParameterList(entry.getKey(), (Object[])value);
			}
			else {
				query.setParameter(entry.getKey(), value);
			}
		}
	}
	
	//2.1:统计记录数
	public String getCountHql(String hql) {
		int index = hql.toUpperCase().indexOf("FROM");
		return "select count(*) " + hql.substring(index);
	}
	
	//2.2:分页
	public List executeQuery(Session session,String hql,PageBean pageBean,Map map) {
		if (pageBean != null && pageBean.isPagination()) {//是分页
			String countHql = getCountHql(hql);
			Query countQuery = session.createQuery(countHql);
			setParameter(countQuery, map);
			pageBean.setTotal(Integer.valueOf(countQuery.getSingleResult().toString()));
			
			Query pageQuery = session.createQuery(hql);
			setParameter(pageQuery, map);
			pageQuery.setFirstResult(pageBean.getStartPage());
			pageQuery.setMaxResults(pageBean.getTotalPage());
			
			return pageQuery.list();
		}
		else {//不分页
			Query query = session.createQuery(hql);
			setParameter(query, map);
			return query.list();
		}
	}
}

BaseDao封装好后,再进行上个案例的操作:要记得继承BaseDao

package com.study.dao;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.query.Query;

import com.study.entity.Book;
import com.study.entity.TreeNode;
import com.zking.util.PageBean;
import com.zking.util.SessionFactoryUtils;
import com.zking.util.StringUtils;

public class BookDao extends BaseDao{
	public List list2(Book book,PageBean pageBean){
		Session session = SessionFactoryUtils.getSession();
		Transaction transaction = session.beginTransaction();
		String hql = "from Book where 1=1";
		Map map = new HashMap();
		if (StringUtils.isNotBlank(book.getBookName())) {
			hql += " and book_name like :book_name";
			map.put("book_name", "%"+book.getBookName()+"%");
		}
		List list = executeQuery(session, hql, pageBean, map);
		transaction.commit();
		session.close();
		return list;
	}
}

代码简洁了不少,至少我们成功去除了重复的代码

 

9.原生sql:

应用场景:当hql不满足需求,或者使用hql不再简化代码,想要使用sql代码时

将createQuery(hql)->createSQLQuery(sql)方法,就能使用sql代码了

 

10.视图映射

例:

1.select * from book a,type b a.tid = b.tid where b.tname like '%玄%'

2.select * from book a,type b a.tid = b.tid where b.tid = 1

3.select * from book a,type b a.tid = b.tid where a.bname like '%完%'

以上是三条联表查询语句,因为业务不同,所以有时要对表进行不同的查询,如果联表的数量非常多,那么写sql时代码就会非常长,所以视图映射就是将重复sql代码封装,然后根据不同的业务,只需要写不同的条件即可

上述代码中重复的地方select * from book a,type b a.tid = b.tid

步骤

1.创建一个视图,将此代码进行封装

create view aaa

as

select * from book a,type b a.tid = b.tid

2.根据业务的不同,对视图添加不同的查询条件

假如我要根据书名查询

select * form aaa where bname like '%完%'

这样就可以达到简化代码的作用

你可能感兴趣的:(Hibernate)