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