Hibernate之HQL

2025-05-19 12:01:35

什么是HQL?

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

HQL与SQL有何不同:

1.HQL

对查询条件进行了面向对象封装,符合编程人员的思维方式,格式:from + 类名 + 类对象 + where + 对象的属性

区分大小写,关键字不区分大小写

从下标0开始计算位置(hibernate5之后不支持)

支持命名参数

2.SQL

sql是面向数据库表查询,格式:from + 表名 + where + 表中字段

不区分大小写

从顺序1开始计算位置

不支持:命名参数

处理返回的结果集

单个对象

多个列段

object【】

对象(多个列段、全部)

Map

这里写了一个JUnit测试类来测试这些效果

注意:测试类中需要设置session,transaction属性,然后就可以在类中写方法论

1. 单个对象 select没有逗号

如果是单个列段的话,就直接可以用String接收对象,这样就避免一些麻烦

/**

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

*/

@Test

public void testList2() {

Query query = session.createQuery("select b.bookName as ss from Book b");

List list = query.list();

for (String b : list) {

System.out.println(b);

}

}

效果:

2.1 Object[]

b.bookId, b.bookName...

如果有两个或者两个以上的列段可以用数组来接收

/**

* 查两个列段及以上,默认返回的是Object【】

*/

@Test

public void testList3() {

Query query = session.createQuery("select b.bookId,b.bookName as ss from Book b");

List list = query.list();

for (Object[] b : list) {

System.out.println(Arrays.toString(b));

}

}

效果:

2.2 book对象

其实两个以上也可以用对象来接收

/**

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

*/

@Test

public void testList5() {

Query query = session.createQuery("select new Book(b.bookId,b.bookName) from Book b");

List list = query.list();

for (Book b : list) {

System.out.println(b);

}

}

效果:

2.2.1 也是用对象来接收

/**

* 返回对象(多个)

*/

@Test

public void testList1() {

Query query = session.createQuery("from Book");

List list = query.list();

for (Book b : list) {

System.out.println(b);

}

}

效果:

3.Map

new Map(b.bookId as bid, b.bookName as bname)

/**

* 注意map是函数,所以不区分大小写,返回的是map集合

*/

@Test

public void testList4() {

Query query = session.createQuery("select new mAp(b.bookId,b.bookName) from Book b");

List list = query.list();

for (Map b : list) {

System.out.println(b);

}

}

效果:

HQL中使用占位符

占位符从下标0开始计算位置

hibernate5之后不再支持占位符

命名参数的使用

/**

* 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)");

query.setParameterList("bookIds", new Integer[] {1,2,4});

// List params = new ArrayList();

// params.add(1);

// params.add(2);

// params.add(4);

// query.setParameterList("bookIds", params);

List list = query.list();

for (Book b : list) {

System.out.println(b);

}

}

命名参数的用法就是:

Query query = session.createQuery("from Book where bookId in (:bookIds)");

query.setParameterList("bookIds", new Integer[] {1,2,4});

连接查询

/**

* HQL支持连接查询

*/

@Test

public void testList7() {

Query query = session.createQuery("select o.orderNo,oi.quantity from Order o,OrderItem oi where o = oi.order");

List list = query.list();

for (Object[] b : list) {

System.out.println(Arrays.toString(b));

}

}

聚合函数

sum 总计

avg 平均值

max 最大

min 最小

count 总数

/**

* HQL支持聚合函数

*/

@Test

public void testList8() {

Query query = session.createQuery("select count(*) from Book");

Long singleResult = (Long) query.getSingleResult();

System.out.println(singleResult);

}

HQL分页

/**

* HQL分页

*/

@Test

public void testList9() {

Query query = session.createQuery("from Book");

query.setFirstResult(2);

query.setMaxResults(3);

List list = query.list();

for (Book b : list) {

System.out.println(b);

}

}

使用HQL实现通用查询

BaseDao类

这就是通用的实体查询类

package com.ht.five.Dao;

import java.util.Collection;

import java.util.List;

import java.util.Map;

import java.util.Map.Entry;

import java.util.Set;

import org.hibernate.Query;

import org.hibernate.Session;

import com.ht.five.Util.PageBean;

/**

* 通用查询类

* @author Administrator

*

*/

public class BaseDao {

/**

* @param map 将要设置的阐述用Map的形式来传递

* @param query 查询对象

*/

public void setParam(Map map, Query query) {

if(map != null && map.size() > 0) {

Object value = null;

Set> entries = map.entrySet();

for (Entry entry : entries) {

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

}

}

}

}

/**

* 传入hql语句 ,返回该语句所查到的总行数

* @param hql

* @return

*/

public String getCountHql(String hql) {

/**

* 下面这种做法的原因是请看这两条hql语句:

* from Book

* select * from Book

*

* 所有要想使这个方法同意就是将from这个位置做截断拼接

*/

//获取到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 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);

this.setParam(map, query);

list = query.list();

}

return list;

}

}

BookDao类

继承BaseDao,可以调用它的查询方法为自己用

package com.ht.five.Dao;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import org.hibernate.Session;

import org.hibernate.Transaction;

import com.ht.five.Util.PageBean;

import com.ht.five.Util.StringUtils;

import com.ht.four.entity.Book;

import com.ht.two.util.SessionFactoryUtils;

/**

* 书本Dao方法

* @author Administrator

*

*/

public class BookDao extends BaseDao{

/**

* 提供查询书籍并分页的方法 该方法基于父类BaseDao实现

* @param book

* @param pageBean

* @return

*/

public List list(Book book, PageBean pageBean){

Session session = SessionFactoryUtils.openSession();

Transaction transaction = session.beginTransaction();

String bookName = book.getBookName();

Map map = new HashMap();

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

if(StringUtils.isNotBlank(bookName)) {

hql += " and bookName like :bookName";

map.put("bookName", bookName);

}

//返回list结果集合

List list = super.executeQuery(session, map, hql, pageBean);

transaction.commit();

session.close();

return list;

}

}

最后在JNUIT测试类中测试

private BookDao bookDao=new BookDao();

/**

* 测试通用查询

*/

@Test

public void testList() {

Book book = new Book();

PageBean pageBean = new PageBean();

pageBean.setPage(2);//根据下标位置来做起始位置(下标从0开始)

pageBean.setRows(3);//设置每页展示3条数据

//带条件查询(模糊查询)

//book.setBookName("%楼%");

List list = this.bookDao.list(book, pageBean);

for (Book b : list) {

System.out.println(b);

}

}

今日分享完毕,谢谢观看!

乌拉圭世界杯名单