HQL:Hibernate Query Language,是Hibernate框架中的查询语言,十分接近于SQL语言!以下介绍一些常用的Hql语句:

一、测试类

Classes类:

<span style="font-family:KaiTi_GB2312;font-size:18px;">package com.bjpowernode.hibernate;

import java.util.Set;

public class Classes {

	private int id;

	private String name;

	private Set students;

	......

}</span>

Student类:

<span style="font-family:KaiTi_GB2312;font-size:18px;">package com.bjpowernode.hibernate;

import java.util.Date;

public class Student {

	private int id;

	private String name;

	private Date createTime;

	private Classes classes;

	public Student() {
} public Student(int id, String name) {
this.id = id;
this.name = name;
} ......
}</span>

初始化数据类:

<span style="font-family:KaiTi_GB2312;font-size:18px;">package com.bjpowernode.hibernate;

import java.text.SimpleDateFormat;
import java.util.Date; import org.hibernate.Session; public class InitData { public static void main(String[] args) {
Session session = HibernateUtils.getSession(); try {
session.beginTransaction(); for(int i=0; i<10; i++){ Classes classes = new Classes();
classes.setName("班级"+i);
session.save(classes); for(int j=0; j<10; j++){
Student student = new Student();
student.setName("班级"+i+"的学生"+j);
student.setCreateTime(randomDate("2009-07-01","2009-09-01")); //在内存中建立由student指向classes的引用
student.setClasses(classes);
session.save(student);
}
} for(int i=0; i<5; i++){
Classes classes = new Classes();
classes.setName("无学生班级"+i);
session.save(classes);
} for(int i=0; i<10; i++){
Student student = new Student();
student.setName("无业游民"+i);
session.save(student);
} session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally{
HibernateUtils.closeSession(session);
}
} /**
* 获取随机日期
* @param beginDate 起始日期,格式为:yyyy-MM-dd
* @param endDate 结束日期,格式为:yyyy-MM-dd
* @return
*/
private static Date randomDate(String beginDate,String endDate){
try {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date start = format.parse(beginDate);
Date end = format.parse(endDate); if(start.getTime() >= end.getTime()){
return null;
} long date = random(start.getTime(),end.getTime()); return new Date(date);
} catch (Exception e) {
e.printStackTrace();
}
return null;
} private static long random(long begin,long end){
long rtn = begin + (long)(Math.random() * (end - begin));
if(rtn == begin || rtn == end){
return random(begin,end);
}
return rtn;
}
}</span>

二、常用的hql语句

2.1,简单属性查询

单一属性:

<span style="font-family:KaiTi_GB2312;font-size:18px;">//返回结果集属性列表,元素类型和实体类中的属性类型一致
List students = session.createQuery("select name from Student").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
String name = (String)iter.next();
System.out.println(name);
}</span>

多个属性:

<span style="font-family:KaiTi_GB2312;font-size:18px;">//查询多个属性,返回对象数组集合,数组元素的类型与查询的属性类型一致
//数组的长度与select中查询的属性个数一致
List students = session.createQuery("select id, name from Student").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + ", " + obj[1]);
}</span>

多个属性查询,返回实体对象

<span style="font-family:KaiTi_GB2312;font-size:18px;">//可以使用hql返回Student对象
<span style="color:#ff6666;">//需要提供构造函数</span>
List students = session.createQuery("select new Student(id, name) from Student").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getId() + ", " + student.getName());
}</span>

2.2,带参数的查询

拼串查询

<span style="font-family:KaiTi_GB2312;font-size:18px;">List students = session.createQuery("select s.id, s.name from Student s where s.name like '%0%'").list();</span>

使用?方式传递参数,索引从0开始,值能使用单引号引起来

<span style="font-family:KaiTi_GB2312;font-size:18px;">//方法链编程,建议采用此种方式
List students = session.createQuery("select s.id, s.name from Student s where s.name like ?")
.setParameter(0, "%0%")
.list();</span>
<span style="font-family:KaiTi_GB2312;font-size:18px;">//采用 ?方式,查询学号为1,2,3,4,5的学生
List students = session.createQuery("select s.id, s.name from Student s where s.id in(?, ?, ?, ?, ?)")
.setParameter(0, 1)
.setParameter(1, 2)
.setParameter(2, 3)
.setParameter(3, 4)
.setParameter(4, 5)
.list();</span>

使用 :参数名的方式传递参数

<span style="font-family:KaiTi_GB2312;font-size:18px;">//可以采用 :参数名 的方式传递参数
List students = session.createQuery("select s.id, s.name from Student s where s.name like :myname")
.setParameter("myname", "%0%")
.list();</span>
<span style="font-family:KaiTi_GB2312;font-size:18px;">//采用 :参数名 方式,查询学号为1,2,3,4,5的学生
List students = session.createQuery("select s.id, s.name from Student s where s.id in(:ids)")
.setParameterList("ids", new Object[]{1, 2, 3, 4, 5})
.list();</span>

2.3,对象导航查询(通过cross join查询,慎重考虑使用)

<span style="font-family:KaiTi_GB2312;font-size:18px;">List students = session.createQuery("from Student s where s.classes.name like '%2%'")
.list();</span>

2.4,外置命名查询

实体映射文件中的配置:

<span style="font-family:KaiTi_GB2312;font-size:18px;"><query name="queryStudent">
<![CDATA[
select s from Student s where s.id <?
]]>
</query> </span>

查询时的调用:

<span style="font-family:KaiTi_GB2312;font-size:18px;">List students = session.getNamedQuery("queryStudent")
.setParameter(0, 10)
.list();</span>

2.5,分页查询

<span style="font-family:KaiTi_GB2312;font-size:18px;">List students = session.createQuery("from Student")
.setFirstResult(1)
.setMaxResults(2)
.list();</span>

setFirstResult:表示第一条记录的索引;setMaxResults:表示每页显示的最大记录数

2.6,原生sql语句查询

<span style="font-family:KaiTi_GB2312;font-size:18px;">List students = session.createSQLQuery("select * from t_student").list();</span>

2.7,统计查询(实际上是调用函数的查询)

<span style="font-family:KaiTi_GB2312;font-size:18px;">String hql = "select c.name, count(s) from Classes c join c.students s group by c.name order by c.name";
List students = session.createQuery(hql).list();</span>

2.8,过滤查询

实体对象映射文件配置:

<pre name="code" class="html"><span style="font-family:KaiTi_GB2312;font-size:18px;">	<class name="com.bjpowernode.hibernate.Student" table="t_student">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<property name="createTime"/>
<many-to-one name="classes" column="classesid"/>
<span style="color:#ff6666;"><filter name="testFilter" condition="id < :myid"></filter></span>
</class> <span style="color:#ff6666;"><filter-def name="testFilter">
<filter-param type="integer" name="myid"/>
</filter-def></span></span>

<span style="font-family:KaiTi_GB2312;font-size:18px;">session.enableFilter("testFilter")
.setParameter("myid", 10);
List students = session.createQuery("from Student").list();</span>

以上就是一些常用的hql语句,下面介绍一下Hibernate中的N+1问题

三、N+1问题

所谓的N+1问题实际上是指Hibernate在查询的时候,发出了N+1条sql语句:

1:发出一条查询id列表的语句

N:根据id发出N条sql语句,加载相关对象

Iterator接收查询结果:

<pre name="code" class="java"><span style="font-family:KaiTi_GB2312;font-size:18px;">Iterator iter = session.createQuery("from Student").iterate();
while (iter.hasNext()) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}</span>

控制台打印结果:

解决方案:

每次执行list操作后会将数据放到session的缓存中(一级缓存),所以采用iterate的时候, 首先会发出一条查询id列表的语句,再根据id到缓存中加载相应的数据,如果缓存中存在与之匹配的数据,则不再发出根据id查询的sql语句,直接使用缓存中的数据。



所以,使用list去接收查询的语句,可避免N+1的问题。但如果缓存中存在数据,使用Iterate会比使用List性能高!

注意: 在默认情况下,每次执行list查询实体对象都会发出查询语句,除非配置了查询缓存。虽然一级缓存中存在Student数据,但list不用,所以仍然发出查询语句, 其实list就是只向缓存中放入数据,而不利用缓存中的数据

四、总结

以上就是使用Hibernate框架在查询中需要注意的一些问题。在谈到N+1问题的时候,说到了缓存。那么缓存是提高Hibernate整个框架性能的一个重要因素,下篇博客谈谈Hibernate的缓存机制。它的一级缓存、二级缓存等的开启和管理!

【Hibernate 6】常用的hql语句以及N+1问题的更多相关文章

  1. hibernate中常用的Hql语句总结

    // HQL: Hibernate Query Language. // 特点: // >> 1,与SQL相似,SQL中的语法基本上都可以直接使用. // >> 2,SQL查询 ...

  2. J2EE进阶(十七)Hibernate中常用的HQL查询方法(getHibernateTemplate())

    J2EE进阶(十七)Hibernate中常用的HQL查询方法(getHibernateTemplate())   当我们使用Hibernate进行数据的CRUD操作时,利用模版进行操作不失为一种方法. ...

  3. 常用的Hql语句

    // HQL: Hibernate Query Language.// 特点:// >> 1,与SQL相似,SQL中的语法基本上都可以直接使用.// >> 2,SQL查询的是表 ...

  4. 常用的Hql语句(转)

    原文地址:http://blog.csdn.net/v123411739/article/details/28644007     尊重原创,请访问原文地址 // HQL: Hibernate Que ...

  5. Hibernate的查询语言之HQL(二)——Hibernate查询的from字句

    from 是最简单的HQL语句,也是最基本的HQL语句.from 关键字后紧跟持久化类的类名.例如: from Person 表明从Person持久化类中取出全部的实例. 大部分时候,推荐位该Pers ...

  6. HibernateCRUD基础框架(2)-HQL语句构造器(HqlQueryBuilder,HqlUpdateBuilder)

    上篇讲述了最基本的实体类,本篇接着讲述HQL语句构造器,包括查询和更新等. 优点:通过面向对象的方式构造HQL语句,更快捷,不需要手动拼接HQL. 缺点:封装可能降低性能,只能支持常用的和较为简单的H ...

  7. hql语句查询实体类采用list方法的返回结果集

    在hibernate中,用hql语句查询实体类,采用list方法的返回结果为一个List,该List中封装的对象分为以下三种情况:1.查询全部字段的情况下,如"from 实体类", ...

  8. Hibernate框架HQL语句

    这篇随笔将会记录hql的常用的查询语句,为日后查看提供便利. 在这里通过定义了三个类,Special.Classroom.Student来做测试,Special与Classroom是一对多,Class ...

  9. hibernate -- HQL语句总结

    1. 查询整个映射对象所有字段 //直接from查询出来的是一个映射对象,即:查询整个映射对象所有字段 String hql = "from Users"; Query query ...

随机推荐

  1. Hadoop学习2--Linux准备及环境准备

    1.环境安装: 虚拟机:VMware Player 系统:Ubuntu12 注意事项:注意位数,包括系统,java,Hadoop 2.切换账号 当前登录账号是自己的账号,如果想切换到root,且是第一 ...

  2. 黄聪:C#里如何使用WebBrowser获取处理AJAX生成的网页内容?

    等待网页执行完毕(AJAX执行后). 使用webBrowser1.Document.Body.OuterHtml可以获取到AJAX产生的网页内容.

  3. Java的最大优势还是跨平台么?

    之前码农界有码农说Java的最大优势是跨平台,真的是这样么?其实当时网络没这么火爆的时候,确实是这样的,但现在这已然不是了. 跨平台还是Java的最大优势么? 有跨平台需求的仅仅是客户端应用,而不是服 ...

  4. PLSQL_Database Link的基本概念和用法(概念)

    2014-06-08 Created By BaoXinjian

  5. GL_Oracle Erp月结和年节流程讨论(概念)

    2014-02-06 Created By BaoXinjian

  6. Codeforces Round #366 (Div. 2) C Thor(模拟+2种stl)

    Thor 题意: 第一行n和q,n表示某手机有n个app,q表示下面有q个操作. 操作类型1:app x增加一条未读信息. 操作类型2:一次把app x的未读信息全部读完. 操作类型3:按照操作类型1 ...

  7. HDU 2176 取(m堆)石子游戏(Nim)

    取(m堆)石子游戏 题意: Problem Description m堆石子,两人轮流取.只能在1堆中取.取完者胜.先取者负输出No.先取者胜输出Yes,然后输出怎样取子.例如5堆 5,7,8,9,1 ...

  8. NeHe OpenGL教程 第三十三课:TGA文件

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  9. mrp功能分类

    mrp主要有六大功能子系统:[工程管理子系统].[销售管理子系统].[计划管理子系统].[采购管理子系统].[库存管理子系统].[MRP运行管理子系统].[工程管理子系统]主要功能:产品/物料编码表. ...

  10. firebug下载时出现there was an error loading firebug

    打开Firefox -> Preferences -> Advance ->Certificates 将Query OSCP....前面的checkbox取消