天天看点

【Hibernate之Hql语句五】前言总结

目录

  • 前言
    • Hql的介绍
    • Hql语句的特性
      • HQL语句支持占位符
      • HQL支持连接查询
      • HQL支持聚合函数
      • HQL分页
    • Hql特性的运用(模糊查询,分页)
      • 运用基本特性逻辑
      • 运用辅助Dao方法减少开发周期(BaseDao)
  • 总结

前言

本章节我们将会通过结合之前的案例来详细讲解一下Hql语句的运用。

比如

【Hibernate之Hql语句五】前言总结

在里面的 “from Order” 这就算是Hql语句的一种

那么查询所有,用这种方法就可以实现,那么问题就这么来了,

如果我想传个参数,然后根据参数查询,或者用来分页,那么这个时候Hql语句又如何去写?

欧克,Let`go

Hql的介绍

Hql: 简称Hibernate的面向对象语言

Hibernate Query Language的缩写

那么让我们来看一看Hql和sql语句的区别。

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

嘛,接下来就是一整套的测试数据

Hql语句的特性

返回对象(多个)

public void testList1() {
		Query query = session.createQuery("from Book");
		List<Book> list = query.list();
		for (Book b : list) {
			System.out.println(b);
		}
	}
           

返回单个列段,用字符串就可以接受

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【】

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集合

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

查两个列段及以上,也可返回对象,前提是有对应的构造函数

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

HQL语句支持占位符

public void testList6() {

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

		List<Book> list = query.list();
		for (Book b : list) {
			System.out.println(b);
		}
	}
           

HQL支持连接查询

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

HQL支持聚合函数

public void testList8() {
		Query query = session.createQuery("select count(*) from Book");
		Long singleResult = (Long) query.getSingleResult();
		System.out.println(singleResult);
	}
           

HQL分页

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特性的运用(模糊查询,分页)

运用基本特性逻辑

通过上面的特性讲解,大概也了解了基本特性

所以我们就可以来写个方法来测试是否可以使用模糊查询。

为了大家理解,就不直接放代码,而是一步一步来。

一,根据参数的有无而拼接hql语句

一般而言我们是直接从request请求中获取map集合里面的参数

可这边因为是测试,所以没有前端这一说。

切记不要搞混了!!!

//获取参数
String bookName = book.getBookName();

String Hql = "from Book where 1=1 ";

//根据参数的有无而拼接hql语句,所用的是命名参数
if(StringUtils.isNotBlank(bookName)) {
	Hql+=" and bookName like :bookname ";
}
           

里面的 :bookname 是命名参数的写法 ,也就是已键值对的方式存在.

二,下面需要对query所赋值

ok,在我的看法中,我就直接分为两个部分,在这个部分中就是对query所赋值

横竖都是赋值,只不过需要在赋值之前加个判断

//下面需要对query所赋值
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());
}
		
           

三,整体代码展示

其实如果把之前的查询所有,和我刚才讲的来想一想的话其实还是差不多的。

偌:

public List<Book> list1(Book book,PageBean pageBean) {
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		

		String Hql = "from Book where 1=1 ";

		//下面需要对query所赋值
		Query query = session.createQuery(Hql);
		List<Book> list = query.list();
		
		transaction.commit();
		session.close();
		return list;
	}
	
           

啊啊,整体代码就是这样:

public List<Book> list1(Book book,PageBean pageBean) {
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		
		//获取参数
		String bookName = book.getBookName();
		
		String Hql = "from Book where 1=1 ";
		
		//根据参数的有无而拼接hql语句
		if(StringUtils.isNotBlank(bookName)) {
			Hql+=" and bookName like :bookname ";
		}
		
		//下面需要对query所赋值
		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<Book> list = query.list();
		
		transaction.commit();
		session.close();
		return list;
	}
	
           

希望大家能看的懂,也能理解我的思路拉(✪ω✪)

运用辅助Dao方法减少开发周期(BaseDao)

在上面我们已经知道如何裸写代码了,那么这个还怕个啥子嘛。

那么为了理解,我就先给大家看写好后,所引用的Dao

是不是看到后,感觉是不是跟我的上面分解第一步差不多,只不过整体上没有了第二部分的代码

ps:用到了map那是因为是用来模拟从jsp所传值,请不要乱想!!

public List<Book> list2(Book book,PageBean pageBean) {
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		
		//获取参数
		String bookName = book.getBookName();
		
		String Hql = "from Book where 1=1 ";
		Map<String, Object> map = new HashMap<>();
		
		//根据参数的有无而拼接hql语句
		if(StringUtils.isNotBlank(bookName)) {
			Hql+=" and bookName like :bookname ";
			map.put("bookname", bookName);
		}
		
		List<Book> list = executeQuery(session, map, Hql, pageBean);
		
		transaction.commit();
		session.close();
		return list;
	}
           

1,BaseDao中的一键赋值(辅助方法)

这个家伙的话大家也别到处乱想了,汗,

方法本身主要是在本类里面使用,作用:快速给query赋值

map是外面所传过来的,咱先不管是否是jsp传过来,还是自己创建的map集合。

这个就是将Map集合里面的数据全部给query赋值

public void setParam(Map<String, Object> map , Query query) {
		
		if(map!=null&&map.size()>0) {
			Set<Entry<String, Object>> entrySet = map.entrySet();
			Object value = null;
			for (Entry<String, Object> entry : entrySet) {
				value = entry.getValue();
				//获取来自参数的map的键值对
				//判断每一个的值的类型然后分别对待
				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);
				}
				
			}
		}
	}
           

2,BaseDao中的查询总行数(辅助方法)

这个比较简单,就是根据Hql去查询表内总行数

public String getCountHql(String Hql) {
		
		int indexOf = Hql.toUpperCase().indexOf("FROM");
		return "select count(*)  "+Hql.substring(indexOf);
	}
           

3,所使用方法和判断是否分页(引用方法)

这个,其实并不难,重点在需要分页的里面

它使用了两次 seesion.createQuery ,不明白的话就会搞混了,

其实就是给pageBean的total属性所赋值。

额,怎么说呢,就是因为你模糊查询后,所查到的数据绝对不是整张表的的条数嘛,

所以需要重新设置一下,

public List executeQuery(Session session,Map<String, Object> map,String Hql,PageBean pageBean ) {
		List list = null;
		if(pageBean!=null && pageBean.isPagination()) {
			
			//------找到这个表内有多少数据
			String countHql = this.getCountHql(Hql);
			Query countQuery = session.createQuery(countHql);
			this.setParam(map, countQuery);
			pageBean.setTotal(countQuery.getSingleResult().toString());
			
			//----------------------------------
			//给需要分页的query设置值
			Query query = session.createQuery(Hql);
			query.setFirstResult(pageBean.getStartIndex());
			query.setMaxResults(pageBean.getRows());
			
			this.setParam(map, query);
			list = query.list();
			
		}
		else {//不用分页的话
			Query query = session.createQuery(Hql);
			//给query的参数赋值
			this.setParam(map, query);
			list = query.list();
			
		}
		
		return list;
	}
           

总结

哇,超额完成啊,有木有,

这次是我想一下,看能不能改一下风格滴,

本人觉得每个地方的讲解还算详细的啦|ू・ω・` )

Thanks♪(・ω・)ノ希望对大家有所帮助

继续阅读