hibernate之Hql

本文详细介绍了Hibernate的Hql查询语言,包括Hql的基本概念、与SQL的区别、结果集类型、占位符使用、连接查询、聚合函数以及分页操作。通过实例演示了Hql的各种查询方式,探讨了分页查询的改进方法,旨在帮助读者更好地掌握面向对象的查询语言。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Hql基本知识

1.什么是Hql

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

2.Hql和Sql的区别

1、sql 面向数据库表查询。

2、hql 面向对象查询。

3、hql : from 后面跟的 类名+类对象 where 后 用 对象的属性做条件。

4、sql: from 后面跟的是表名 where 后 用表中字段做条件查询。

5、在Hibernate中使用查询时,一般使用Hql查询语句。

6、HQL,即Hibernate的查询语言跟SQL非常相像。不过HQL与SQL的最根本的区别,就是它是面向对象的。

7.大小写敏感:因为HQL是面向对象的,而对象类的名称和属性都是大小写敏感的,所以HQL是大小写敏感的。

8sql的占位符是?,而hql的是命名参数

3.返回的结果集

下面多种结果结果,我们一个使用的也就2,3个而已
3.1方法多个对象

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

结果:

Book [bookId=1, bookName=西游记, price=50.0]
Book [bookId=2, bookName=红楼梦, price=50.0]
Book [bookId=3, bookName=水浒, price=50.0]
Book [bookId=4, bookName=三国演义, price=50.0]
Book [bookId=5, bookName=斗罗大陆, price=10.0]
Book [bookId=6, bookName=洞中强者, price=10.0]

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

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

结果:

西游记
红楼梦
水浒
三国演义
斗罗大陆
洞中强者

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

结果:

[1, 西游记]
[2, 红楼梦]
[3, 水浒]
[4, 三国演义]
[5, 斗罗大陆]
[6, 洞中强者]

3.4集合(注意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);
		}
	}

结果:

{0=1, 1=西游记}
{0=2, 1=红楼梦}
{0=3, 1=水浒}
{0=4, 1=三国演义}
{0=5, 1=斗罗大陆}
{0=6, 1=洞中强者}

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

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

结果:
查询两个字段,另一个没有查就是null

Book [bookId=1, bookName=西游记, price=null]
Book [bookId=2, bookName=红楼梦, price=null]
Book [bookId=3, bookName=水浒, price=null]
Book [bookId=4, bookName=三国演义, price=null]
Book [bookId=5, bookName=斗罗大陆, price=null]
Book [bookId=6, bookName=洞中强者, price=null]

4.Hql使用占位符

Hql的占位符是命名参数,不像sql一样一个?,然后就直接赋值
给你们看一个例子:
这里要注意的是:注销的不是错误的,而是其他的赋值方式

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

结果:

Book [bookId=1, bookName=西游记, price=50.0]
Book [bookId=2, bookName=红楼梦, price=50.0]
Book [bookId=4, bookName=三国演义, price=50.0]

5.连接查询

这里要提到的就是,两个实体类是需要有关系的才能建立连接查询。
这里我们查询的一个订单表,一订单项,而一个订单有多个订单项,一个订单项只有一个订单,这就是他们的联系。查询的结果是订单的名称,订单项的价格

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

结果:

[p20, 24]
[p20, 25]
[p30, 2]
[p30, 3]
[p30, 4]

6.聚合函数

Hql里面也是有聚合函数的如:sum, avg, max, min, count
这里就举一个例子:

@Test
	public void testList8() {
		Query query = session.createQuery("select count(*) from Book");
		//getSingleResult  是用来获取单条记录的
		Long singleResult = (Long) query.getSingleResult();
		System.out.println(singleResult);
	}

结果:6

7.Hql的分页

hql:可以根据方言生成分页语句
* setForstResilt:设置起始下标
* setMaxReults:设置偏移量
一个致命的缺点就是没有查询

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

结果:

Book [bookId=3, bookName=水浒, price=50.0]
Book [bookId=4, bookName=三国演义, price=50.0]
Book [bookId=5, bookName=斗罗大陆, price=10.0]

对于分页的改进

1.0版本

我们自己来写分页
dao方法

/**
	 * 需求:
	 * 	写一个带查询条件的并且能分页方法
	 * 
	 * @param book
	 * @param pagebean
	 * @return
	 */
	public List<Book> list1(Book book,PageBean pagebean) {
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		
		List<Book> list = null;
		String hql = "from Book where 1=1";
		String bookName = book.getBookName();
		if(StringUtils.isNotBlank(bookName)) {
			hql += " and bookName like :bookName";
		}
		//query 相当于前面sql所用的preparestatement
		Query query = session.createQuery(hql);
		if(StringUtils.isNotBlank(bookName)) {
			query.setParameter("bookName", bookName);
		}
		//通过写上述代码就发现,同样的if判断写了两次
		
		if(pagebean != null && pagebean.isPagination()) {
			query.setFirstResult(pagebean.getStartIndex());
			query.setMaxResults(pagebean.getRows());
		}
		list = query.list();
		
		transaction.commit();
		session.close();
		return list;
	}
	

测试代码:

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

结果:Book [bookId=6, bookName=洞中强者, price=10.0]

2.0版本

上述的到方法的代码有重复的判断,下面我们就对他进行一个改进
写一个baseBao

package com.hu.five.util;

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

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

/**
 * 1.设置参数的问题
 * 2.分页代码重复的问题
 * 
 * sql 的通用分页的时候
 * getConuntSql(Sql);
 * select conunt(1) from (sql) t
 * 
 * getConuntHql(Hql);
 * hql = "from Book where bookName like :bookName"
 * hql = "select * from new Book(bid.....) where bookName like :bookName"
 * select count(1) hql
 * @author Administrator
 *
 */
public class BaseDao {
	
	/**
	 * 
	 * @param 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>> entrySet = map.entrySet();
			for (Entry<String, Object> entry : entrySet) {
				//有时候它并不是单纯的字符串
				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);
				}
			}
		}
	}
	
	//根据from关键字进行截取,拿到from的下标
	public String getConuntSql(String hql) {
		int index = hql.toUpperCase().indexOf("FROM");		
		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()) {
			//拿到counthql
			String countHql = getConuntSql(hql);
			//获取query对象
			Query createQuery = session.createQuery(countHql);
			//设置参数
			this.setParam(map, createQuery);
			
			pageBean.setTotal(createQuery.getSingleResult().toString());
			
			//返回结果集
			Query query = session.createQuery(hql);
			//给预定义hql语句执行对象中的参数赋值,有多少赋值多少
			this.setParam(map, query);
			query.setFirstResult(pageBean.getStartIndex());
			query.setMaxResults(pageBean.getRows());
			list = query.list();
			
		}else {
			Query query = session.createQuery(hql);
			//给预定义hql语句执行对象中的参数赋值,有多少赋值多少
			this.setParam(map, query);
			list = query.list();
		}
		return list;
	}
}

dao方法继承BaseDao

public List<Book> list2(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<Book> list = super.executeQuery(session, map, hql, pagebean);
	
		transaction.commit();
		session.close();
		return list;
	}

测试

@Test
	public void testList2() {
		Book book = new Book();
		PageBean pageBean = new PageBean();
		//pageBean.setPage(2);
		book.setBookName("%强%");
		List<Book> list1 = this.bookDao.list2(book, pageBean);
		for (Book b : list1) {
			System.out.println(b);
		}	
	}

结果:
Book [bookId=6, bookName=洞中强者, price=10.0]

小编刚刚出道,有什么写的不对的地方就指出来,大家一起进步。有喜欢的就点亮一下旁边的小红心吧,给小编的一个支持。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值