027 hibernate查询语言(HQL)

  • 概述:数据查询与检索是Hibernate中的一个亮点,相对其他ORM实现而言,Hibernate提供了灵活多样的查询机制。
  • 标准化对象查询(Criteria Query):以对象的方式进行查询,将查询语句封闭为对象操作。优点:可主动性好,符合Java程序员的编码习惯。缺点:不够成熟,不支持投影(projection)或统计函数(aggregation)

n   例:查询用户名以“J”开头的所有用户

Criteria c = session.createCreateria(User.class);

c.add(Expression.like(“name”,”J%”));

List users = c.list();

  • Hibernate语句查询(Hibernate Query Language,HQL)它是完全面向对象的查询语句,查询功能非常强大,具备多态、关联待特性。
  • Native SQL Queries(原生SQL查询)直接使用标准SQL语言或跟特定数据库相关的SQL进行查询。
  • Ø  注:除了Java类与属性的名称外,查询语句对大小写并不敏感。 所以 SeLeCTsELEct 以及 SELECT 是相同的,但是 org.hibernate.eg.FOO 并不等价于 org.hibernate.eg.Foo 并且 foo.barSet 也不等价于 foo.BARSET
  • HQL用面向对象的方式生成SQL

n   以类和属性来代替表和数据列

n   支持多态

n   支持各种关联

n   减少了SQL的冗余

  • HQL支持所有的关系数据库操作

n   连接(joins,包括inner/outer/full joins),笛卡尔积(Cartesian products)

n   投影(projection)

n   聚合(Aggregation,max,avg)和分组(group)

n   排序(ordering)

n   子查询(subqueries)

n   SQL函数(SQL function calls)

HQL语言是一套中立语言:它与任何数据库都没有关系,通过hibernate的方言自动的把HQL语言翻译成各种数据库语言

027-1 HQL简单例子

例一:查询用户名以“J”开头的所有用户:

Query query = session.createSQLQuery("from User user where user.name like ‘J%‘");

List users = query.list();

注:User是指User实体类 并重新起别名为user

user.name:表示实体类的属性

HQL中不使用表名,字段名,全部使用实体类、实体类的属性

例二:复杂例子:从User和Group中查找属于“admin”组的所有用户

Query query = session.createQuery("from User user where user.group.name=‘admin‘");

注:user.group.name:表示实体类User中组(group)中的名称(name)

传统的SQL

select user.userId as userId, user.name as name, user.groupId as groupid, user.idCardId as IdCardId from TBL_USER USER, TBL_GROUP group where (group.groupName=’admin’ and user.groupid=groupid.groupid)

语法:HQL语言中的关键字不区分大小写,但是属性和类名区分大小写,from后面跟的是类名,不是表名。

HQL演示环境

学生与班级的关联映射

Classes实体类:

public class Classes {

private int id;

private String name;

//一对多通常使用Set来映射,Set是不可重复内容。

//注意使用Set这个接口,不要使用HashSet,因为hibernate有延迟加载,

private Set students;

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Set getStudents() {

return students;

}

public void setStudents(Set students) {

this.students = students;

}

}

Student实体类:

public class Student {

private int id;

private String name;

private Date createTime;

private Classes classes;

public Date getCreateTime() {

return createTime;

}

public void setCreateTime(Date createTime) {

this.createTime = createTime;

}

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Classes getClasses() {

return classes;

}

public void setClasses(Classes classes) {

this.classes = classes;

}

}

Classes实体类的映射文件:

<hibernate-mapping>

<class name="com.wjt276.hibernate.Classes" table="t_classes">

<id name="id" column="id">

<generator class="native"/>

</id>

<property name="name" column="name"/>

<!--

<set>标签 映射一对多(映射set集合),name="属性集合名称"

然后在用<key>标签,在多的一端加入一个外键(column属性指定列名称)指向一的一端

再采用<one-to-many>标签说明一对多,还指定<set>标签中name="students"这个集合中的类型

要使用完整的类路径(例如:class="com.wjt276.hibernate.Student")

inverse="false":一的一端维护关系失效(反转) :false:可以从一的一端维护关系(默认);true:从一的一端维护关系失效

-->

<set name="students" inverse="true">

<key column="classesid"/>

<one-to-many class="com.wjt276.hibernate.Student"/>

</set>

</class>

</hibernate-mapping>

Student实体类映射文件:

<hibernate-mapping>

<class name="com.wjt276.hibernate.Student" table="t_student">

<id name="id" column="id">

<generator class="native"/>

</id>

<property name="name" column="name"/>

<property name="createTime"/>

<many-to-one name="classes" column="classesid"/>

</class>

</hibernate-mapping>

初始化演示需要的数据:

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("2008-01-01",

"2008-03-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

*/

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;

}

}

org.hibernate.Query  Session.createQuery返回执行HQL查询的Query实例。

Session.createSQLQuery返回执行本地SQL查询的Query实例。

 

  • List org.hibernate.Query.list():返回结果集列表。注:不同的HQL语句,返回不同的结果集列表

1.简单属性的查询

01 单一属性查询

查询:所有学生称名:

query.list():返回是单一属性的集合,

元素类型和实体类中相应的属性类型一致,就是说List的类型取决于实体类属性的类型。

session = HibernateUtils.getSession();

tx = session.beginTransaction();

//单一属性查询,query.list()返回是单一属性的集合,元素类型和实体类中相应的属性类型一致,就是说List

//的类型取决于实体类属性的类型

List student = session.createQuery("select name from Student").list();

for (Iterator iter = student.iterator(); iter.hasNext();){

String name = (String)iter.next();//实体类Student的属性name类型为String

System.out.println(name);

}

tx.commit();

注:select name from Student

Student:不是数据库中的表,而是Student实体类,所以需要区分大小写

name:不是表中的字段名,而是Student实体类中的属性,所以需要区分大小写

02 多个属性查询

查询:所有学生的ID、姓名

Query.list():返回结果集合元素是对象数组

数组元素的类型和对应的属性在实体类中的类型一致

数组的长度取决与select中属性的个数

数组中元素的顺序,也取决与select中属性的顺序

session = HibernateUtils.getSession();

tx = session.beginTransaction();

//查询多个属性,其返回结果集合元素是对象数组

//数组元素的类型和对应的属性在实体类中的类型一致

//数组的长度取决与select中属性的个数

//数组中元素的顺序,也取决与select中属性的顺序

List student = session.createQuery("select id, name from Student").list();

for (Iterator iter = student.iterator(); iter.hasNext();){

//集合中的元素是2个长度对象的数组(因为select查询了id,name两个属性)

Object[] obj = (Object[])iter.next();

//数据组中第一个元素是id,类型是int;第二个元素是name,类型是String(因为select中是id(int),name(String)顺序)

System.out.println(obj[0] + "," + obj[1]);

}

tx.commit();

03 查询一个或多个属性,要求返回实体对象

Query.list():返回结果集合元素是实体类对象

* 查询一个或多个属性,要求返回实体对象,

* 可采用HQL动态实例化实体对象

* 实现条件:实体类中要一个构造方法,其参数是你需要查询的属性,还需要一个无参构造方法(这是实体类的必需条件之一)

* 然后在HQL语句中采用new 一个实体对象就可以了。

* 如果查询所有学生的的id、姓名,要求list返回Student对象:select new Student(id,name) from Student

* 这样session.createQuery().list()返回的就是Student实体对象

session = HibernateUtils.getSession();

tx = session.beginTransaction();

//如果认为返回数组不够对象化,可以采用hql动态实例化Student对象,此时list中为Student对象集合。

//当然Student实体类中要有以id、name为参数的构造方法,和一个无参构造方法(是实体类必要条件之一)

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

}

04 使用别名查询

HQL语句中,可以使用别名查询,可以使用空格或as进行命名别名

1、select s.id, s.name from Student s

2、select s.id, s.name from Student as s

2.实体对象查询

 2.1简单的实体对象查询

* 语法:from 实体类(如果:session.createQuery("from Student");

* 可以忽略select

* Query.list():返回实体对象集合(Student对象集合)

session = HibernateUtils.getSession();

tx = session.beginTransaction();

//返回Student对象的集合

//可以忽略select

List students = session.createQuery("from Student").list();

for (Iterator iter = students.iterator(); iter.hasNext();){

Student student = (Student)iter.next();

System.out.println(student.getName());

}

tx.commit();

2.2 实体对象使用别名查询

实体类对象查询,也可以使用别名,同样可以使用空格或as

1、List students = session.createQuery("from Student s").list();

2、List students = session.createQuery("from Student as s").list();

2.3使用select查询实体对象

如果使用select查询实体对象,必须采用别名,可以用空格或as关键字, select后直接跟别名就可以了。

1、List students = session.createQuery("select s from Student s").list();

2、List students = session.createQuery("select s from Student as s").list();

2.4 HQL不支持select * from ……

HQL不支持select * from ……查询,否则会抛异常,但*可以用是特定的函数中。

2.5 query.iterate查询数据

* query.iterate()方式返回迭代查询

* 会开始发出一条语句:查询所有记录ID语句

* Hibernate: select student0_.id as col_0_0_ from t_student student0_

* 然后有多少条记录,会发出多少条查询语句。

* n + 1问题:n:有n条记录,发出n条查询语句;1 :发出一条查询所有记录ID语句。

* 出现n+1的原因:因为iterate(迭代查询)是使用缓存的,

第一次查询数据时发出查询语句加载数据并加入到缓存,以后再查询时hibernate会先到ession缓存(一级缓存)中查看数据是否存在,如果存在则直接取出使用,否则发出查询语句进行查询。

session = HibernateUtils.getSession();

tx = session.beginTransaction();

/**

* 出现N+1问题

* 发出查询id列表的sql语句

* Hibernate: select student0_.id as col_0_0_ from t_student student0_

*

* 再依次发出根据id查询Student对象的sql语句

* Hibernate: select student0_.id as id1_0_, student0_.name as name1_0_,

* student0_.createTime as createTime1_0_, student0_.classesid as classesid1_0_

* from t_student student0_ where student0_.id=?

*/

Iterator students = session.createQuery("from Student").iterate();

while (students.hasNext()){

Student student = (Student)students.next();

System.out.println(student.getName());

}

tx.commit();

2.6 query.list()和query.iterate()的区别

先执行query.list(),再执行query.iterate,这样不会出现N+1问题,

* 因为list操作已经将Student对象放到了一级缓存中,所以再次使用iterate操作的时候

* 它首先发出一条查询id列表的sql,再根据id到缓存中取数据,只有在缓存中找不到相应的

* 数据时,才会发出sql到数据库中查询

List students = session.createQuery("from Student").list();

for (Iterator iter = students.iterator(); iter.hasNext();){

Student student = (Student)iter.next();

System.out.println(student.getName());

}                       System.out.println("---------------------------------------------------------");

// 不会出现N+1问题,因为list操作已经将数据加入到一级缓存。

Iterator iters = session.createQuery("from Student").iterate();

while (iters.hasNext()){

Student student = (Student)iters.next();

System.out.println(student.getName());

}

2.7 两次query.list()

* 会再次发出查询sql

* 在默认情况下list每次都会向数据库发出查询对象的sql,除非配置了查询缓存

* 所以:虽然list操作已经将数据放到一级缓存,但list默认情况下不会利用缓存,而再次发出sql

* 默认情况下,list会向缓存中放入数据,但不会使用数据。

List students = session.createQuery("from Student").list();

for (Iterator iter = students.iterator(); iter.hasNext();){

Student student = (Student)iter.next();

System.out.println(student.getName());

}

System.out.println("------------------------------------------------");

//会再次发现SQL语句进行查询,因为默认情况list只向缓存中放入数据,不会使用缓存中数据

students = session.createQuery("from Student").list();

for (Iterator iter = students.iterator(); iter.hasNext();){

Student student = (Student)iter.next();

System.out.println(student.getName());

}

时间: 2024-11-09 10:02:28

027 hibernate查询语言(HQL)的相关文章

【HQL】hibernate查询语言hql

hibernate查询语言hql 在hql中关键字不区分大小写,通常小写,类的名称和属性名称必须区分大小写 1.简单属性查询[重要] * 单一属性查询,返会属性结果集列表,元素类型和实体类中相应的类型一致 * 多个属性查询,多个属性查询返会对象数组,对象数组的长度取决于属性的个数 对象数组中元素的类型取决于属性在实体类中的类型 * 如果认为返会数组不够对象化,可以使用hql动态实例化Student对象 参见:SimplePropertyQueryTest.java 2.实体对象查询[重要] *

Hibernate查询语言——HQL

HQL(Hibernate Query Language)查询语言是完全面向对象的查询语言,它提供了更加面向对象的封装,可以理解如多态.继承和关联. HQL的基本语法如下: select "对象.属性名" from "对象" where "过滤条件" group by "对象.属性名" having "分组条件" order by "对象.属性名"

Hibernate查询语言

HQL(Hibernate Query Language)查询语言是完全面向对象的查询语言,它提供了更加面向对象的封装,它可以理解如多态.继承和关联的概念.HQL看上去和SQL语句相似,但它却提供了更加强大的查询功能. 1. 了解HQL语言 HQL语句与SQL语句是相似的,其基本的使用习惯也与SQL相同.由于HQL是面向对象的查询语言,说以它需要从目标对象中查询信息并返回匹配单个实体对象或多个实体对象的集合,而SQL语句是从数据库表中查找指定的信息,返回的是单条信息或多条信息的集合. 注意:HQ

HQL: Hibernate查询语言

HQL: Hibernate查询语言 Hibernate配备了一种非常强大的查询语言,这种语言看上去很像SQL.但是不要被语法结构 上的相似所迷惑,HQL是非常有意识的被设计为完全面向对象的查询,它可以理解如继承.多态 和关联之类的概念. 第 15 章 HQL: Hibernate查询语言 Hibernate配备了一种非常强大的查询语言,这种语言看上去很像SQL.但是不要被语法结构 上的相似所迷惑,HQL是非常有意识的被设计为完全面向对象的查询,它可以理解如继承.多态 和关联之类的概念. 15.

类型:。net;问题:HQL;结果:HQL: Hibernate查询语言

HQL: Hibernate查询语言 Hibernate配备了一种非常强大的查询语言,这种语言看上去很像SQL.但是不要被语法结构 上的相似所迷惑,HQL是非常有意识的被设计为完全面向对象的查询,它可以理解如继承.多态 和关联之类的概念. 第 15 章 HQL: Hibernate查询语言 Hibernate配备了一种非常强大的查询语言,这种语言看上去很像SQL.但是不要被语法结构 上的相似所迷惑,HQL是非常有意识的被设计为完全面向对象的查询,它可以理解如继承.多态 和关联之类的概念. 15.

Hibernate 的查询语言 HQL 与高级查询

Hibernate  的查询语言 HQL  与高级查询 数据库操作实现类的开发 import java.util.List; import org.hibernate.Query; import org.hibernate.SQLQuery; import org.hibernate.Session; import org.hibernate.Transaction; import org.sf.dao.IDepartmentDao; import org.sf.entity.Departmen

Hibernate查询语言(HQL)

HQL是Hibernate Query Language即Hibernate查询语言 1.执行HQL语句的步骤: (1).获取Session对象 Configuration cfg = new Configuration(); SessionFactory sessionFactory = cfg.buildSessionFactory(); Session session = sessionFactory.getCurrentSession(); (2).编写HQL语句 (3).创建Query

Hibernate之HQL介绍

Hibernate中提供了多种检索对象的方式,主要包括以下种类: 导航对象图检索方式:根据已经加载的对象导航到其他对象 OID检索方式:根据对象的OID来检索对象 HQL检索方式:使用面向对象的HQL查询语言 QBC检索方式:使用QBC(Query By Criteria)API来检索对象.这种API封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口 本地SQL检索方式:使用本地数据库的SQL查询语句 本文主要介绍第三种方式,也就是HQL检索对象. HQL(Hibernate Quer

Hibernate之HQL总结

hibernate运行过程: Hibernate作用 1.hibernate是java应用和关系数据库之间的桥梁,她负责java对象和关系数据库之间的映射. 2.hibernate内部封装了通过JDBC访问数据库的操作,向上层应用提供了面向对象的数据访问API. Hibernate API简介 1.提供访问数据库操作(session,transaction,query) 2.配置hibernate接口(configuration) 3.回调接口(Interceptor,Lifecycle,Vai