是Hibernate Query Language的缩写
hql 与 sql 的区别/异同
hql | sql |
---|---|
类名/属性 | 表名/列名 |
区分大小写,关键字不区分大小写 | 不区分大小写 |
别名 : ?,从下标0开始计算位置(hibernate5之后不支持) | 别名:?,从顺序1开始计算位置 |
:命名参数 | 不支持:命名参数 |
面向对象的查询语言 | 面向结构查询语言 |
hql 语句介绍
package com.hyf.xFive.test;
import java.util.ArrayList;
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.hyf.four.entity.Book;
import com.hyf.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);
}
}
/**
* 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)");
// 查询id 为 1 , 2,4
// 传数组
// 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);
}
}
/**
* 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));
}
}
/**
* HQL支持聚合函数
*/
@Test
public void testList8() {
Query query = session.createQuery("select count(*) from Book");
Long singleResult = (Long) query.getSingleResult();
System.out.println(singleResult);
}
/**
* 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);
}
}
}
query.list(); 查询多条数据
query.getSingleResult() 查询多条数据单条
版本一
public List<Book> list(Book book,PageBean pageBean){
Session session = SessionFactoryUtils.openSession();
String hql = "from Book where 1=1";
String bname = book.getBookName();
if(StringUtils.isNotBlank(bname)) {
hql +=" and bookName like :bookName";
}
Query query = session.createQuery(hql );
// 当 bname 不等于空的时候赋值
if(StringUtils.isNotBlank(bname)) {
query.setParameter("bookName", bname);
}
// 分页
if(pageBean !=null && pageBean.isPagination()) {
// 设置pageBean 起始下标
query.setFirstResult(pageBean.getStartIndex());
query.setMaxResults(pageBean.getRows());
}
List list = query.list();
return list;
}
问题:每增加一个查询就需要写一个这种语句,如果数量过多的话,导致重复代码过多。
版本二
通用 beasDao
package com.hyf.xFive.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;
/**
* 基于hql语句的通用查询通用工具类
* 1、需要给拼接的hql语句的命名参数赋值(可以简化的)
* 2、分页(可以简化)
*
* 基于sql的分页的查询的做法
* 1、首先要查询出符合条件的总记录数
* 2、返回符合条件的记录
* 参数:sql ,pageBean,Class clz
* 1、 countSql = select count(*) from (sql) t;
* 2、 pageSql = sql + " limit " +start +" , " +rows
*
* 基于hql的分页的查询的做法
* hql = from Book where bookName like "%xxx%"
* hql = select * from Book where bookName like "%圣墟%"
* 1、countHql = select count(*) hql
*
*
* @author 17628
*
*/
public class BeasDao {
/**
* @param query 里面包含了带有参数的hql 语句,需要等待赋值
* "from Book where 1=1 and bookName like :bookName
* @param map
* =request.getParameterMap();
*/
public void setParam(Query query, Map<String, Object> paramMap) {
if(paramMap !=null && paramMap.size()!=0) {
// 遍历 paramMap 集合 得到前台传来的数据
Set<Entry<String, Object>> entrySet = paramMap.entrySet();
for (Entry<String, Object> entry : entrySet) {
// 遍历之后,给 query 赋值
String key = entry.getKey();
Object value = entry.getValue();
// 我们这里要考虑以下 传过来的是数组 还是集合
if(value instanceof Object[]) {
// 当 value 为数组时
query.setParameter(key, (Object [])value);
}else if(value instanceof Collection){
// 当 value 为集合时
query.setParameter(key, (Collection)value);
}else {
// 普通字符串
query.setParameter(key, value);
}
}
}
}
/**
* 拼装符合条件的总记录数
* 2、countHql = select count(*) hql
* hql 可以能为以下两种情况
* hql = from Book where bookName like "%xxx%"
* hql = select * from Book where bookName like "%圣墟%"
* 所以通过截取得到 from和后面的条件
*
* @param hql
* @return
*/
public String getCountSql(String hql) {
// toUpperCase() 转大写 。因为hql 区分大小写 ,我们干脆把hql语句转成 大写
// indexOf() 取 FROM 的下标
int fromIndex = hql.toUpperCase().indexOf("FROM");
return "select count(*)"+hql.substring(fromIndex);
}
/**
* 基于hql通用查询方法
*
* @param hql 最终传来的 hql 语句
* @param pageBean 分页
* @param paramMap =request.getParameterMap(); 前台传来的 值
* @param session 创建 Query 对象
* @return
*/
public List executeQuery(String hql,PageBean pageBean,Map<String,Object> paramMap,Session session) {
List list = null;
Query query = null;
if(pageBean != null && pageBean.isPagination()) {
// 获取查询的总数量
String countHql =getCountSql(hql);
Query createQuery = session.createQuery(countHql);
this.setParam(createQuery, paramMap);
//将总行数放入PageBean对象
pageBean.setTotal(createQuery.getSingleResult().toString());
// 返回符合条件的记录
query = session.createQuery(hql);
//给预定于的hql语句的命名参数赋值。有多少赋多少
this.setParam(query, paramMap);
//设置开始位置(下标从0开始)
query.setFirstResult(pageBean.getStartIndex());
//这是偏移量,就是一页展示几条数据
query.setMaxResults(pageBean.getRows());
list=query.list();
}else {
// 不分页
query=session.createQuery(hql);
this.setParam(query, paramMap);
list=query.list();
}
return list;
}
}
BookDao
它需要继承 BaseDao
public List<Book> listPlus(Book book,PageBean pageBean){
Session session = SessionFactoryUtils.openSession();
String hql = "from Book where 1=1";
String bname = book.getBookName();
// 这个是jsp 自动传递过来的,不与要手写,模拟一下
Map<String, Object> map = new HashMap<String, Object>();
if(StringUtils.isNotBlank(bname)) {
hql +=" and bookName like :bookName";
map.put("bookName", bname);
}
List list = super.executeQuery(hql, pageBean, map, session);
session.close();
return list;
}
JUnit 测试
@Test
public void testList11() {
Book b = new Book();
PageBean pageBena = new PageBean();
pageBena.setPage(3);
// b.setBookName("%圣墟%");
List<Book> list = this.bookDao.listPlus(b, pageBena);
for (Book book : list) {
System.out.println(book);
}
}