hibernate之HQL

本文深入讲解Hibernate Query Language (HQL),包括HQL与SQL的区别、HQL的基本语法、使用技巧及高级特性,如连接查询、聚合函数等,并通过具体实例展示了如何在Java项目中运用HQL进行高效的数据操作。

简介

  1. 什么是HQL?
    HQL是Hibernate Query Language的缩写是一种查询语言。
  2. hql和sql区别/异同
    | HQL | SQL |
    | 类名/属性 |表名/列名|
    | 区分大小写,关键字不区分大小写 | 不区分大小写|
    | 别名 | 别名|
    | ?,从下标0开始计算位置(hibernate5之后不支持)|?,从顺序1开始计算位置|
    |:命名参数 |不支持:命名参数|
    |面向对象的查询语言 | 面向对象的查询语言 |
  3. 处理返回的结果集
  • 返回对象(多个)查询所有
  • 返回单个列段,用字符串就可以接受,返回String类型 只查询书的名称
  • 查两个列段及以上,默认返回的是Object【】,查询两个列的数据
  • 注意map是函数,所以不区分大小写,返回的是map集合,用函数来查询多个列段。
  • 查两个列段及以上,也可返回对象,前提是有对应的构造函数
  • HQL语句支持占位符,用变量名代替(?占位符 从下标0开始计算位置)
  • HQL支持连接查询 (select o.orderNo,oi.quantity from Order o,OrderItem oi where o = oi.order)
  • HQL支持聚合函数(sum avg max min count)
  • HQL分页 同样的可以自动根据方言生成分页语句 setFirstResult:设置起始下标
    setMaxResults:设置偏移量

HqlTest功能演示

package com.hibernate.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.hibernate.enetiy.Book;
import com.hibernate.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);
   	}
   }
   
   /**
    * 返回单个列段,用字符串就可以接受
    * 返回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);
   	}
   }
   
   /**
    * 查两个列段及以上,默认返回的是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);
   	}
   }
   
   /**
    * HQL语句支持占位符
    * 用变量名代替?
    */
   @Test
   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支持连接查询
    */
   @Test
   public void testList7() {
   	//select * from t_hibernate_order o,t_hinernate_item oi where  o.order_id=oi.oid
   	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支持聚合函数
    */
   @Test
   public void testList8() {
   	//还支持 sum  avg max min
   	Query query = session.createQuery("select count(*) from Book");
   	//getSingleResult是用来获取单条记录的
   	Long singleResult = (Long) query.getSingleResult();
   	System.out.println(singleResult);
   }
   
   /**
    * HQL分页
    * 
    * 同样的可以自动根据方言生成分页语句
    * oracle
    * select * from  (select t.*,rownum rn hql t where t.rn >5 ) t1 where 
    */
   @Test
   public void testList9() {
   	Query query = session.createQuery("from Book");
   	//这是是开始位置 切记是从0开始滴
   	query.setFirstResult(1);
   	//分页偏移量 就是一页展示几条数据
   	query.setMaxResults(3);
   	List<Book> list = query.list();
   	for (Book b : list) {
   		System.out.println(b);
   	}
   }
}

用HQL实现通用方法

  • BaseDao
package com.hibernate.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、分页代码重的问题
 * 
 * @author 林凡
 *
 */
public class BaseDao {
	/**
	 * 通用的参数设值方法
	 * @param map  参数键值对集合
	 * @param query	预定义处理的hql对象
	 * 
	 */
	
	private 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);
				}
			}
		}
	}

	public String getCountHql(String hql) {
//		* hql ="from Book where bookName like :bookName"
//			*  hql ="select * from new Book(bid,bookName) where bookName like :bookName"
				 
		//获取到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);
			//给预定义hql语句执行对象中的参数赋值,有多少赋值多少
			this.setParam(map, query);
			list =query.list();
		}
		return list;
	}
}

调用BaseDao方法来执行自己的方法

  • BookDao
public class BookDao extends BaseDao{
	/**
	 * 需求
	 * 写一个带查询条件的并且能分页方法
	 * @param book
	 * @param pageBean
	 * @return
	 */
	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";
		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<Book> list =query.list();
		transaction.commit();
		session.close();
		return list;
	}
	/**
	 * 提供查询书籍并分页的方法 该方法基于父类BaseDao实现
	 * @param book
	 * @param pageBean
	 * @return
	 */
	
	public List<Book> list12(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集合就ok了
			map.put("bookName", bookName);
		}
		//返回list结果集合
		List<Book> list =super.executeQuery(session, map, hql, pageBean);
		
		transaction.commit();
		session.close();
		return list;
	}
	
}

测试方法

  • BookDaoTest
public class BookDaoTest {
	private BookDao bookDao = new BookDao();

@Test
	public void testList1() {
		Book book =new Book();
		PageBean pageBean  =new PageBean();
//		book.setBookName("%楼%");
		List<Book> list  =this.bookDao.list1(book, pageBean);
		for (Book b : list) {
			System.out.println(b);
		}
	}
	
	@Test
	public void testList2() {
		Book book =new Book();
		PageBean pageBean  =new PageBean();
		pageBean.setPage(2);//设置从第三条开始查询(0为启始位置)
		pageBean.setRows(3);//设置每页展示3条数据
//		pageBean.setPagination(false);
//		book.setBookName("%楼%");(like查询带楼字的书)
		List<Book> list  =this.bookDao.list12(book, pageBean);
		for (Book b : list) {
			System.out.println(b);
		}
	}
	
}
标题基于Spring Boot的音乐播放网站设计与实现研究AI更换标题第1章引言介绍音乐播放网站的研究背景、意义、国内外现状及论文方法与创新点。1.1研究背景与意义阐述音乐播放网站在当今数字化时代的重要性与市场需求。1.2国内外研究现状分析国内外音乐播放网站的发展现状及技术特点。1.3研究方法以及创新点概述论文采用的研究方法及在设计与实现上的创新点。第2章相关理论与技术基础总结音乐播放网站设计与实现所需的相关理论和技术。2.1Spring Boot框架介绍介绍Spring Boot框架的基本原理、特点及其在Web开发中的应用。2.2音乐播放技术概述概述音乐播放的基本原理、流媒体技术及音频处理技术。2.3数据库技术选型分析适合音乐播放网站的数据库技术,如MySQL、MongoDB等。第3章系统设计详细介绍音乐播放网站的整体设计方案。3.1系统架构设计阐述系统的层次结构、模块划分及各模块的功能。3.2数据库设计介绍数据库表结构、关系及数据存储方式。3.3界面设计用户界面的设计原则、布局及交互方式。第4章系统实现详细介绍音乐播放网站的具体实现过程。4.1开发环境与工具介绍开发所需的软件、硬件环境及开发工具。4.2核心功能实现阐述音乐播放、搜索、推荐等核心功能的实现细节。4.3系统测试与优化介绍系统测试的方法、过程及性能优化策略。第5章研究结果与分析呈现音乐播放网站设计与实现的研究结果。5.1系统功能测试结果展示系统各项功能的测试结果,包括功能完整性、稳定性等。5.2用户反馈与评价收集并分析用户对音乐播放网站的使用反馈与评价。5.3对比方法分析将本设计与实现与其他类似系统进行对比分析,突出优势与不足。第6章结论与展望总结音乐播放网站设计与实现的研究成果,并展望未来发展方向。6.1研究结论概括音乐播放网站设计与实现的主要成果及创新点。6.2展望指出当前研究的不足,提出未来改进方向及可
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值