不知不觉又到了hibernate的最后一篇了,只感觉时光飞逝~,岁月如梭~!

转眼之间,我们就···························,好吧,想装个X,结果装不下去了,还是直接开始吧·

前面我们已经把hibernate中添加、删改、修改和根据ID得到对象的方法都学习了,但如何才能查询出多条记录呢?比如我想查询所有姓黄的作者,查询标题包含“中”字的博客等。这一篇就来介绍查询。

hibernate有两种检索(查询)数据的方式,分别是HQL(Hibernate Query Language)和QBC(Query By Criteria)。官方推荐使用HQL的方式,不要问我为什么,因为············就算你很诚恳的询问我,我也不会告诉你。反正用过HQL的人都说好。

HQL提供的语法与SQL非常相似,支持动态参数绑定、投影查询、分页查询、连接查询、分组查询、内置聚集函数、子查询等,可以说是数据库中常用的查询功能,HQL都可以实现。

当然,HQL并不是只能查询,其实也可以用来执行insert、delete和update语句(使用HQL语法),只不过我们今天不讲,大家有兴趣自己练习一下就OK了。

HQL使用步骤:

  1. )获取Session对象

  2. )编写HQL语句

  3. )获得Query对象

  4. )动态绑定参数

  5. )调用执行方法

今天玩点花样,我们通过常用的查询功能来讲解每个语法吧。

一、查询所有的作者

1
2
3
4
5
6
7
8
9
10
11
    public static void main(String[] args) {
        Session session = HibernateSessionFactory.getSession();
        //查询所有作者
        String hql = "from Author";
        Query query = session.createQuery(hql);
        List<Author> list = query.list();
        for (Author author : list) {
            System.out.println("姓名:"+author.getUsername());
        }
        HibernateSessionFactory.closeSession();
    }

注意:

1. 查询Author的所有属性时可以省略select部分

2. from后面的Author是Java中的实体类的类名,在HQL语句中 select或from之类的关键字不区别大小写,但类名、属性名必须和实体类大小写完全相同。

结果:

二、查询作者ID为2的所有博客

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    public static void main(String[] args) {
        Session session = HibernateSessionFactory.getSession();
        //查询ID为2的作者的博客
        Author author = (Author)session.get(Author.class, 2);
        //把作者对象当作参数进行查询
        //String hql = "from Blog b where b.author=?";     //占位符方式
        String hql = "from Blog b where b.author=:author";   //参数名方式
        Query query = session.createQuery(hql);
        //添加参数
        //query.setEntity(0, author);      //占位符方式
        query.setEntity("author", author);   //参数名方式
        //执行查询
        List<Blog> list = query.list();
        //遍历结果
        for (Blog blog : list) {
            System.out.println("标题:"+blog.getTitle());
        }
        HibernateSessionFactory.closeSession();
    }

注意:

这儿的条件,where后面的author是Blog实体类中的author属性,参数是什么类型就可以使用setxxx传对应的类型

参数有两种写法:一种是使用“?”,相当于占位符,另一种使用“:xxx”,相当于根据名字传值。

结果:

三、查询标题包含“中”字的所有博文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    public static void main(String[] args) {
        Session session = HibernateSessionFactory.getSession();
        //查询标题包含“中”字的所有博文
        String hql = "from Blog b where b.title like ?";
        Query query = session.createQuery(hql);
        //添加参数
        query.setString(0, "%中%");    //参数名方式
        //执行查询
        List<Blog> list = query.list();
        //遍历结果
        for (Blog blog : list) {
            System.out.println("标题:"+blog.getTitle());
        }
        HibernateSessionFactory.closeSession();
    }

注意:

like后面不能写成'%?%',这种写法是错误的。必须在外面拼接好前后的“%”,再作为参数传递给query对象。

结果:

四、按博文创建日期倒序排列所有博文

1
2
3
4
5
6
7
8
9
10
11
12
13
    public static void main(String[] args) {
        Session session = HibernateSessionFactory.getSession();
        //按日期倒序排列所有博文
        String hql = "from Blog b order by b.createTime desc";
        Query query = session.createQuery(hql);
        //执行查询
        List<Blog> list = query.list();
        //遍历结果
        for (Blog blog : list) {
            System.out.println("时间:"+blog.getCreateTime()+",标题:"+blog.getTitle());
        }
        HibernateSessionFactory.closeSession();
    }

注意:

反复看了三遍,发现真的没有哪儿需要注意,我也很绝望啊!

结果:

五、假如每页显示3篇博文,在上一查询的基础上,查询第2页的博文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    public static void main(String[] args) {
        Session session = HibernateSessionFactory.getSession();
        int pageNO = 2;       //页码
        int pageCount = 3;    //每页数量
        //按日期倒序排列所有博文
        String hql = "from Blog b order by b.createTime desc";
        Query query = session.createQuery(hql);
        query.setFirstResult((pageNO-1)*pageCount);        //起始位置
        query.setMaxResults(pageCount);                    //记录数量
        //执行查询
        List<Blog> list = query.list();
        //遍历结果
        for (Blog blog : list) {
            System.out.println("时间:"+blog.getCreateTime()+",标题:"+blog.getTitle());
        }
        HibernateSessionFactory.closeSession();
    }

注意:

setFirstResult表示查询的第一条记录的下标,setMaxResults表示查询几条记录,一般分页都是传递页码(第几页)过来。至于实际项目中的分页如何编写,等后面我们讲常用功能模块时再来说明吧。

结果:

六、根据手机号查询作者(确定最多只有一条记录)

1
2
3
4
5
6
7
8
9
10
11
12
    public static void main(String[] args) {
        Session session = HibernateSessionFactory.getSession();
        //查询手机号为13612349876的作者
        String hql = "from Author a where a.phone=?";
        Query query = session.createQuery(hql);
        //添加参数
        query.setString(0, "13612349876");
        //执行查询
        Author author = (Author)query.uniqueResult();
        System.out.println("姓名:"+author.getUsername()+",联系方式:"+author.getPhone());
        HibernateSessionFactory.closeSession();
    }

注意:

确定查询结果最多只有一条记录时,可以使用uniqueResult()方法。

结果:


单表查询并且返回所有属性的查询语法,到这儿就告一段落。

接下来进行部分属性的查询、分组查询、多表查询和子查询。


查询语法加上select子句后,返回的结果有以下几种接收方式。

  1. object[]数组

  2. List集合

  3. Map集合

  4. 自定义实体类

我们还是通过例子来学习吧:查询所有博文,只返回标题和内容。

1
2
3
4
5
6
7
8
9
10
11
    public static void main(String[] args) {
        Session session = HibernateSessionFactory.getSession();
        //查询所有博文,返回标题和内容
        String hql = "select title,content from Blog";
        Query query = session.createQuery(hql);
        List<Blog> list = query.list();
        for (Blog blog : list) {
            System.out.println("标题:"+blog.getTitle());
            System.out.println("\t内容:"+blog.getContent());
        }
    }

运行会发现出现以下异常:

大概意思就是不能把Object转换成Blog类型。

接下来,我们使用上面所说的四种方式来解决这个问题,结果就不再一一展示了。

1、Object[]数组方式

1
2
3
4
5
6
7
8
9
10
11
12
13
    public static void main(String[] args) {
        Session session = HibernateSessionFactory.getSession();
        //查询所有博文,返回标题和内容
        String hql = "select title,content from Blog";
        Query query = session.createQuery(hql);
        //执行查询
        List<Object[]> list = query.list();
        for (Object[] objects : list) {
            System.out.println("标题:"+objects[0]);
            System.out.println("\t内容:"+objects[1]);
        }
        HibernateSessionFactory.closeSession();
    }

注意:如果只查询一个属性时,返回的就不再在数组,而是单个Object。

 

2、List集合方式

1
2
3
4
5
6
7
8
9
10
11
12
13
    public static void main(String[] args) {
        Session session = HibernateSessionFactory.getSession();
        //查询所有博文,返回标题和内容
        String hql = "select new List(title,content) from Blog";
        Query query = session.createQuery(hql);
        //执行查询
        List<List> list = query.list();
        for (List lst : list) {
            System.out.println("标题:"+lst.get(0));
            System.out.println("\t内容:"+lst.get(1));
        }
        HibernateSessionFactory.closeSession();
    }

注意:HQL语句中的select后面,使用new List()的方式来接受数据。

3、Map集合方式

1
2
3
4
5
6
7
8
9
10
11
12
13
    public static void main(String[] args) {
        Session session = HibernateSessionFactory.getSession();
        //查询所有博文,返回标题和内容
        String hql = "select new Map(title as t,content as c) from Blog";
        Query query = session.createQuery(hql);
        //执行查询
        List<Map> list = query.list();
        for (Map map : list) {
            System.out.println("标题:"+map.get("t"));
            System.out.println("\t内容:"+map.get("c"));
        }
        HibernateSessionFactory.closeSession();
    }

注意:如果new Map()中的属性没有取别名,则在for循环中通过get("下标")的形式来读取数据,特别注意,这儿是字符串"下标",而不是整数。

4、自定义实体类

4.1)在Blog实体类中添加包含标题和内容的构造方法

1
2
3
4
5
    //新增构造方法
    public Blog(String title, String content){
        this.title = title;
        this.content = content;
    }

4.2)测试类中的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
    public static void main(String[] args) {
        Session session = HibernateSessionFactory.getSession();
        //查询所有博文,返回标题和内容
        String hql = "select new Blog(title,content) from Blog";
        Query query = session.createQuery(hql);
        //执行查询
        List<Blog> list = query.list();
        for (Blog blog : list) {
            System.out.println("标题:"+blog.getTitle());
            System.out.println("\t内容:"+blog.getContent());
        }
        HibernateSessionFactory.closeSession();
    }

注意:HQL语句中查询几个属性,则在对应的实体类中必须的对应的构造方法。

四种方式到这儿就介绍完毕,至于哪种好哪种差,那就看个人习惯了。

继续后面的案例:

七、查询每个作者的博文数量(分组查询)

1
2
3
4
5
6
7
8
9
10
11
12
13
    public static void main(String[] args) {
        Session session = HibernateSessionFactory.getSession();
        //查询每个作者的博文数
        String hql = "select author, count(b) from Blog b group by b.author";
        Query query = session.createQuery(hql);
        //执行查询
        List<Object[]> list = query.list();
        for (Object[] objects : list) {
            System.out.print("作者:"+((Author)objects[0]).getUsername());
            System.out.println(",博文数:"+objects[1]);
        }
        HibernateSessionFactory.closeSession();
    }

注意:分组之后的统计数据没办法保存到实体类,所以只能使用前三种方式来接受数据。

结果:

八、查询所有的博文和作者(作者账号已经注销的不查(也就是博文表中作者ID为null的不查),多表联合查询)

1
2
3
4
5
6
7
8
9
10
11
12
13
    public static void main(String[] args) {
        Session session = HibernateSessionFactory.getSession();
        //查询所有博文,包括作者信息
        String hql = "from Blog b inner join b.author a";
        Query query = session.createQuery(hql);
        //执行查询
        List<Object[]> list = query.list();
        for (Object[] objs : list) {
            System.out.println("标题:"+((Blog)objs[0]).getTitle());
            System.out.println("\t作者:"+((Author)objs[1]).getUsername());
        }
        HibernateSessionFactory.closeSession();
    }

注意:inner join后面的是Blog类中的author属性,Ojbect[]数组中保存的是两个对象。左连接的功能,大家自己尝试吧。

结果:

 

九、最后一个,查询博文数是2的所有作者(子查询)

1
2
3
4
5
6
7
8
9
10
11
12
    public static void main(String[] args) {
        Session session = HibernateSessionFactory.getSession();
        //查询所有博文,包括作者信息
        String hql = "from Author a where (select count(b) from a.blogs b)=2";
        Query query = session.createQuery(hql);
        //执行查询
        List<Author> list = query.list();
        for (Author author : list) {
            System.out.println("作者:"+author.getUsername());
        }
        HibernateSessionFactory.closeSession();
    }

结果:

呼~~~~~~,想不到我也能写出这么长的文章。

破了我30多年来的历史记录啊!!!激动得要了。

恳请大大给我加个推荐吧~~

“软件思维”博客地址:51CTO,博客园,感兴趣的小伙伴可以去看相关的其它博文。

《Java从入门到放弃》入门篇:hibernate查询——HQL的更多相关文章

  1. Java性能测试从入门到放弃-概述篇

    Java性能测试从入门到放弃-概念篇 辅助工具 Jmeter: Apache JMeter是Apache组织开发的基于Java的压力测试工具.用于对软件做压力测试.JMeter 可以用于对服务器.网络 ...

  2. Flink从入门到放弃(入门篇1)-Flink是什么

    戳更多文章: 1-Flink入门 2-本地环境搭建&构建第一个Flink应用 3-DataSet API 4-DataSteam API 5-集群部署 6-分布式缓存 7-重启策略 8-Fli ...

  3. Flink从入门到放弃(入门篇2)-本地环境搭建&构建第一个Flink应用

    戳更多文章: 1-Flink入门 2-本地环境搭建&构建第一个Flink应用 3-DataSet API 4-DataSteam API 5-集群部署 6-分布式缓存 7-重启策略 8-Fli ...

  4. Flink从入门到放弃(入门篇3)-DataSetAPI

    戳更多文章: 1-Flink入门 2-本地环境搭建&构建第一个Flink应用 3-DataSet API 4-DataSteam API 5-集群部署 6-分布式缓存 7-重启策略 8-Fli ...

  5. Flink从入门到放弃(入门篇4) DataStreamAPI

    戳更多文章: 1-Flink入门 2-本地环境搭建&构建第一个Flink应用 3-DataSet API 4-DataSteam API 5-集群部署 6-分布式缓存 7-重启策略 8-Fli ...

  6. Vue.js2.0从入门到放弃---入门实例

    最近,vue.js越来越火.在这样的大浪潮下,我也开始进入vue的学习行列中,在网上也搜了很多教程,按着教程来做,也总会出现这样那样的问题(坑啊,由于网上那些教程都是Vue.js 1.x版本的,现在用 ...

  7. 转-Vue.js2.0从入门到放弃---入门实例(一)

    http://blog.csdn.net/u013182762/article/details/53021374 标签: Vue.jsVue.js 2.0Vue.js入门实例Vue.js 2.0教程 ...

  8. NodeJs 入门到放弃 — 入门基本介绍(一)

    码文不易啊,转载请带上本文链接呀,感谢感谢 https://www.cnblogs.com/echoyya/p/14450905.html 目录 码文不易啊,转载请带上本文链接呀,感谢感谢 https ...

  9. mysql从入门到放弃-入门知识介绍

    数据库在互联网网站的重要性 简单地说,数据库就是一个存放数据的仓库,这个仓库是按照一定的数据结构来组织和存储的,我们可以通过数据库提供的多种方法来管理数据库里的数据.由于数据库不易扩展,所以,在一个互 ...

随机推荐

  1. linux实训

    目  录 Unit 1 操作系统安装.... 3 1.1 多操作系统安装... 3 1.1.1 VMware简介... 3 1.1.2 VMWare基本使用... 4 1.2 安装Red Hat Li ...

  2. Bootstrap按钮插件

    前面的话 按钮插件提供了一组可以控制按钮多种状态的功能,比如按钮的禁用状态.正在加载状态.正常状态等.本文将详细介绍Bootstrap按钮插件 加载状态 通过按钮可以设计状态提示,当单击按钮时,会显示 ...

  3. 设计模式 - 观察者模式(JDK)

    定义:观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新. 对象:    抽象主题角色:每个抽象主题角色都可以有任意数量的观察者.抽象主题提供可 ...

  4. C# 汉语转拼音

    汉语转拼音或首字母 通常不少网站上有汉语转拼音功能,今天就小记下这段汉语转拼音的代码,自己测试ok,现把代码贴出来,以备日后使用: 效果 用法很简单后台使用到了两个类文件,一个是:ConvertHzT ...

  5. Spring Boot 系列(四)静态资源处理

    在web开发中,静态资源的访问是必不可少的,如:图片.js.css 等资源的访问. spring Boot 对静态资源访问提供了很好的支持,基本使用默认配置就能满足开发需求. 一.默认静态资源映射 S ...

  6. C++第二篇--访问控制

    C++第二篇--访问控制 1. 引入 上一篇博文中从结构体引到了类,类当中不仅有数据成员还有一些函数,这些函数被称为成员函数.今天介绍新的内容,类当中的访问控制. 2. 访问控制 当你不添加任何声明, ...

  7. 把int型非负数转换为英文

    数字转换为英文 输入为int型非负数,最大值为2^31 - 1 = 2 147 483 647 输出为String英文,最大输出为Two Billion One Hundred Forty Seven ...

  8. Spring源码情操陶冶-ContextLoaderListener

    前言:通过实例结合源码的方式解读,其中涉及到的文件来自于博主的Github毕设项目wxServer Note: Springboot应用不在本文章讨论范围 web.xml中启用Spring 在一般的w ...

  9. 基于vs2012的opencv开发环境搭建

    前些日子有个需求,大概描述,实时检测一副动态图每一帧画面上全部的圆形内容,并得到全部圆形的圆心相对坐标以及半径.当时的思路是用Matlab写一个相关图像处理的插件,然后给C#调用.当时没立马动手的原因 ...

  10. XML 入门 - XML 系统教程(1)

    XML (Extensible Markup Language)指可扩展标记语言. 组成 <?xml version="1.0" encoding="UTF-8&q ...