Hibernate个人总结

时间:2023-03-09 01:20:56
Hibernate个人总结

编写Hibernate第一个程序

Hibernate是目前最流行的持久层框架,专注于数据库操作。使用Hibernate框架能够使开发人员从繁琐的SQL语句和复杂的JDBC中解脱出来。Hibernate框架是一种开源的、轻量级的ORM框架,它允许将普通的、传统的Java对象(POJO)映射成持久化类,允许应用程序以面向对象的方式来操作POJO,而Hibernate框架则负责将这种操作转换为底层的SQL操作。

本文将详细介绍什么是ORM以及优势。

重点内容:

什么是ORM,它有什么优势

为项目添加Hibernate支持

开发Hibernate程序的基本步骤

配置hibernate.cfg.xml

创建会话工厂类

创建实体类和映射文件

Hibernate概述

1.什么是ORM

ORM是一种常用的持久化技术,其英文全称是Object/Relation Mapping,中文译名为对象/关系映射。这里所指的对象是指使用的编程语言是面向对象的,而关系则是指使用的数据库是关系型数据库。对象/关系映射则是指完成面向对象语言到关系型数据库的映射,通过该映射用户可以像操作对象一样来操作关系型数据库。其映射关系图如图所示。

Hibernate个人总结

使用ORM后就不需要再与复杂的SQL语句打交道了,通过创建一个持久化类来映射数据库中的一个数据库表,如图所示。其中持久化类的属性则映射到数据库表中的字段。当使用面向对象的方式来操作持久化对象时,ORM框架能自动将这些操作转换成SQL语句,从而完成对数据库的操作。这时开发人员可以将重点放到业务逻辑上去,而不需要关心底层复杂的SQL语句和JDBC代码。

Hibernate个人总结

2.为什么要使用ORM

前面介绍了什么是ORM,但是这是读者可能会有疑问,我已经能够熟练使用JDBC编程了,为什么要我使用ORM呢,使用它有什么好处吗?

使用ORM是整个软件世界发展的趋势,下面将从代码、架构以及性能三方面来分析为什么要使用ORM,使用它的好处究竟有哪些。

1.大大简化了代码

2.将数据库层透明化

3.性能大大优化

3.使用Hibernate框架的优势

目前有几个比较流行的ORM框架,如:Hibernate、iBATIS以及最新的EJB 3版本。其中iBATIS框架是Apache组织提供的另一个轻量级持久层框架,但是并没有实现真正的ORM框架,它只是对象和SQL之间的映射,所以常常也将iBATIS称为SQL Mapping工具,适合于对已有项目的改造。而EJB 3框架是重量级开发框架,不适合轻量级开发。

Hibernate框架是一个完整的持久层解决方案,通过Hibernate的支持,可以通过面向对象的方式进行各种数据库操作,从而取代传统的JDBC数据库操作。Hibernate相对于其他的ORM框架还具有如下优势。

1.Hibernate是免费的、开放源代码的。

2.Hibernate是轻量级开发,实现O/R映射非常简单。

3.Hibernate可扩展性强。

Hibernate拥有众多社区支持。

二、为项目添加Hibernate支持

1.下载和安装Hibernate

要下载Hibernate框架,首先需要访问Hibernate官方站点http://www.hibernate.org。在下载列表中选择下载Hibernate5.07版本,如图所示。

如果开发只需要将所需的架包拷贝到lib目录下即可。如果应用需要使用到其他第三方的JAR,则将第三方JAR添加到lib目录下即可。

Hibernate个人总结

Hibernate个人总结

Hibernate开发入门

1.开发Hibernate程序的基本步骤

在开始实际项目之前,读者首先需要对开发Hibernate程序的基本步骤有所了解,其步骤如下。

(1)创建Hibernate配置文件。

(2)创建会话工厂类SessionFactory。

(3)创建实体类。

(4)创建映射文件。

(5)操作数据库。

2.创建数据库表

在数据中创建一个数据库表student,用来保存学生信息。student表一共包含三个字段,分别用来保存学生的学号、姓名、科目以及成绩。创建student表的SQL语句代码如下。

CREATE TABLE student (
id varchar(10) NOT NULL default '',
name varchar(20) default NULL,
result double(3,1) default NULL,
subject varchar(10) default NULL,
PRIMARY KEY (id)
);

3.创建Hibernate配置文件

Hibernate从其配置文件中读取和数据库有关的信息。Hibernate的配置文件分为两种:一种是XML格式的配置文件;还有一种是资源文件格式的配置文件。

前面通过MyEclipse自动了创建一个XML格式的配置文件,其文件名为hibernate.cfg.xml,该文件保存在WEB-INF\classes目录下。在该配置文件中配置了数据库连接URL、数据库连接驱动、数据库用户名以及用户密码。这里还配置一个属性dialect,该属性用来指定数据库产品类型。因为这里使用的是MySQL数据库,所以设置属性值为org.hibernate.dialect.MySQLDialect。如果需要调试Hibernate,可以将show_sql属性设为true,这样Hibernate在进行持久化操作时会将相应的SQL语句输出到控制台。

4.创建会话工厂类

在使用Hibernate操作数据数据库时,需要得到一个Session对象。通过调用Session对象的方法,才能完成数据库操作,如添加记录、删除记录等等。

Session对象可以通过调用SessionFactory的openSession方法来获得。Session对象必须是要求线程安全的,也就是说每个线程必须拥有一个独立的Session对象。如果不是这样的话,很有可能出现一个线程在进行数据库操作,而另一个线程将Session对象关闭从而抛出异常的情况。

那如何才能做到线程安全呢?这时就要求SessionFactory能够根据不同的线程创建不同的Session对象。在使用MyEclipse进行Hibernate 3支持操作时,会自动添加一个HibernateSessionFactory.java文件,该文件定义了一个会话工厂类。

5.创建实体类

实体类用来映射数据库中一张数据库表,实体类中的属性与数据库表中的字段相对应。持久化类是一个POJO类,不用继承和实现任何类或接口。

public class Student {
private String id; //学生学号
private String name; //学生姓名
private String subject; //学生科目
private double result; //学生成绩
//各属性的setter和getter方法

6.创建对象关系映射文件

关系映射文件用来映射持久化类和数据库表,从而将持久化类中的属性和数据库表中的字段关联起来。其中id元素用来定义主键标识,property元素用来定义其他属性。如果不指定数据库表中字段,则默认使用持久化类中的属性作为其数据表表字段名称。

<hibernate-mapping>
<class name="com.sanqing.po.Student"> <id name="id"> <generator class="assigned"></generator>
</id>
<property name="name"></property> <property name="subject"></property> <property name="result"></property>
</class>
</hibernate-mapping>

7.完成插入数据

如果需要使用Hibernate来插入数据,需要调用Session对象的save方法。save方法接受一个Object类型的参数,该参数为一个封装了所有插入数据的对象。

Session session = HibernateSessionFactory.getSession();
Transaction transaction = null; //声明一个事务对象
try{
transaction = session.beginTransaction(); //开启事务
session.save(student); //保存学生信息
transaction.commit(); //提交事务
System.out.println("添加记录成功!");
}catch(Exception ex) {
ex.printStackTrace();
transaction.rollback(); //事务回滚
}
HibernateSessionFactory.closeSession();//关闭Session

Hibernate配置和会话

Hibernate的配置包括两个重要部分,一个是Hibernate的配置文件Hibernate.cfg.xml,一个是实体类的映射文件,本章将对这两个配置文件进行详细介绍。本章还将一种最新的配置映射关系的方式,使用Annotations配置映射,从而省去繁琐的映射配置文件。本章最后将介绍Hibernate的三种对象状态以及Session的各方法和应用。

重点内容:

使用XML文件配置Hibernate

配置映射文件

使用Annotations配置映射

Hibernate的三种对象状态

Session的各方法以及其应用

配置Hibernate

1.使用XML文件配置Hibernate

使用XML文件配置Hibernate,是目前最常用的配置方式,同样也是Hibernate官方推荐的配置方式。Hibernate默认的配置文件为hibernate.cfg.xml,不过读者也可以使用其他文件名,到时候再在HibernateSessionFactory类中修改配置文件路径就可以了。

在Hibernate配置文件同样有DTD规范,并规范该文件的根节点为<hibernate-configuration>,其代码如下所示。

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
</hibernate-configuration>

2.使用资源文件配置Hibernate

在Hibernate 3以前开发人员一般使用资源文件配置Hibernate,资源文件的格式是键值对形式的。使用资源文件配置Hibernate时,将属性名称作为key值,属性值作为value值。资源文件的后缀名为. properties,需要将该文件放置于CLASSPATH环境变量指定路径的根目录下,在MyEclipse中可以将其直接放置在src根目录下。

hibernate.connection.url=jdbc:mysql://localhost:3306/javaweb
hibernate.connection.username=root
hibernate.connection.password=admin
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true

3.代码动态配置Hibernate

前面介绍的两种方式都是在配置文件进行的配置,这类配置在程序运行中是无法修改的。下面再来介绍一种配置Hibernate的方式,那就是在代码中动态配置Hibernate。

configuration = new Configuration();
configuration. setProperty("connection.url","jdbc:mysql://localhost:3306/javaweb");
configuration.setProperty("connection.username", "root");
configuration.setProperty("connection.password","admin");
configuration.setProperty("dialect", "org.hibernate.dialect.MySQLDialect");
configuration.setProperty("connection.driver_class", "com.mysql.jdbc.Driver");
configuration.setProperty("show_sql", "true");

配置映射文件

1.<hibernate-mapping>元素

映射文件的根节点为<hibernate-mapping>,该节点包含一系列可选的属性,如schema和catalog属性。其中schema属性用来指定数据库表所在的schema名称。如果指定了schema属性,表名则会加上所指定的schema的名字扩展为全限定名;如果没有指定该属性,则不会使用全限定名。<hibernate-mapping>的所有属性以及属性说明如下表所示。

Hibernate个人总结

2.<hibernate-mapping>元素

<class>元素用来配置一个实体类与一个数据库表的关联,其中name属性用来指定实体类的类名,table属性用来指定数据库表的名称。<class>元素除了常用的name属性和table属性外还有其他一些常用属性如下表所示。

Hibernate个人总结

3.<id>元素

每一个实体类中都包含一个唯一的标识,<id>元素能够定义该属性和数据库表中的主键字段的映射。<id>元素同样包含许多的属性,其中name属性用来指定标识属性的名称,type属性用来指定标识属性的Hibernate类型,column属性用来指定数据库表中主键字段的名称。<id>元素还有其他一些常用属性如下表所示。

Hibernate个人总结

4.<property>元素

实体类的标识和数据库表的主键映射完成后,还需要为实体类的其他属性和数据库的其他字段进行映射,这个时候就需要使用到<property>元素。<property>元素的常用属性如下表所示。

Hibernate个人总结

5.其他元素

<class>元素下除了可以添加<id>元素和<property>元素外,还可以添加其他元素。这些元素同样非常重要,本书将在后面的章节进行重点介绍,这里只做简单概述。

◆ <timestamp>元素

◆ <version>元素

◆ <one-to-one>元素

◆ <many-to-one>元素

◆ <import>元素

使用Annotations配置映射

1.使用@Entity注释实体类

@Entity注释用来将一个普通的JavaBean标注为实体类。@Entity注释有一个可选的name属性,用来设置实体名,其默认值为JavaBean的类名。

并不是所有的JavaBean都能被标注为实体类,必须满足如下三个条件。

1.JavaBean类的访问权限只能是public。

2.JavaBean类不能是抽象类。

3.JavaBean中必须有一个无参的构造方法,而且该构造方法的访问权限只能是public。

2.使用@Table注释实体类

@Table注释用来对实体类进行进一步注释,用来配置实体类到数据库表映射的更详细的信息。@Table注释包含四个属性,分别为catalog、name、schema以及uniqueConstraints。

1.catalog属性。

2.name属性。

3.schema属性。

4.uniqueConstraints属性。

3.使用@Id注释实体类标识

@Id注释用来对实体类的标识进行配置,一个实体类一般只有一个标识,所有一个实体类只出现一个@Id注释。

public class Employee {
@Id
private String employeeID;
public String getEmployeeID() { return employeeID;
}
}

4.使用@GenerateValue注释覆盖标识的默认访问策略

使用@Id注释实体类标识时将采用Hibernate的默认访问策略,这时可以使用@GenerateValue注释来覆盖该默认访问策略。@GenerateValue注释包含两个属性,分别为generator和strategy。

1.generator属性,该属性用来指定标识生成器名。标识生成器可以通过@SequenceGenerator、@TableGenerator和@ GenericGenerator来创建,generator属性只需要指定为这些生成器的name属性值即可。

2.strategy属性,该属性用来用来指定标识生成策略。strategy的属性值为一个枚举类型。

5.使用@GenericGenerator注释生成标识生成器

前面介绍了如何使用@GenerateValue注释的strategy属性来指定标识生成策略,但是这些生成策略明显不能满足。这时可以使用@GenericGenerator注释产生标识生成器,然后通过@GenerateValue注释的generator属性来指定该生成器的name属性,这样就可以采用指定的生成器来生成标识。

@GenericeGenerator注释是在Hibernate中定义的,其注释类在org.hibernate.annotations包下,使用该注释可以使用Hibernate内置的各种生成策略从而生成标识。@GenericeGenerator注释包含三个属性,分别为name、parameters和strategy。

1.name属性,该属性用来设置标识生成器名。

2.parameters属性,该属性用来设置标识生成器所需的参数。

3.strategy属性,该属性用来设置Hibernate内置的生成策略。

前面介绍了如何使用@GenerateValue注释的strategy属性来指定标识生成策略,但是这些生成策略明显不能满足。这时可以使用@GenericGenerator注释产生标识生成器,然后通过@GenerateValue注释的generator属性来指定该生成器的name属性,这样就可以采用指定的生成器来生成标识。

@GenericeGenerator注释是在Hibernate中定义的,其注释类在org.hibernate.annotations包下,使用该注释可以使用Hibernate内置的各种生成策略从而生成标识。@GenericeGenerator注释包含三个属性,分别为name、parameters和strategy。

1.name属性,该属性用来设置标识生成器名。

2.parameters属性,该属性用来设置标识生成器所需的参数。

3.strategy属性,该属性用来设置Hibernate内置的生成策略。

6.使用@Column注释实体类非标识属性

一个实体类除了有标示,一般还会有许多的其他属性,这时可以使用@Column注释这些属性。@Column注释最常用的属性为name属性,该属性用来配置数据库表中的字段名。如果不设置该属性值,那么将表示实体类属性名和数据库表字段名一样。

@Column(name="employeeName")
private String employeeName;
@Column(name="employeeSex")
private boolean employeeSex;
@Column(name="employeeBirth")
private Date employeeBirth;
@Column(name="employeePhone")
private String employeePhone;

7.自定义AnnotationSessionFactory类来获得Session对象

前面介绍了如何使用Annotations注释来完成实体类到数据库表的映射,这时还有一点需要特别注意。在以前获得SessionFactory对象是通过调用Configuration对象的buildSessionFactory方法来实现,但是这种方式仅仅支持映射文件方式的映射,不支持Annotations注释映射。

要支持Annotations注释映射必须使用AnnotationConfiguration类,通过该类实例对象的buildSessionFactory方法来获得SessionFactory实例对象。

8.测试Annotations注释是否成功完成映射

通过AnnotationSessionFactory可以加载Annotations注释方式的映射,同样可以通过其buildSessionFactory方法获得SessionFactory对象,同时还可以通过其getSession方法获得Session对象。通过调用Session的对象各种方法就可以完成各类数据库操作,如查询记录、添加记录等等。

在创建测试类之前,首先同样需要在Hibernate配置文件hibernate.cfg.xml中添加映射信息。同映射文件配置映射不同,这里需要使用在< mapping>元素中指定其class属性为需要映射的实体类,代码如下所示。

<mapping class="com.sanqing.po.Employee"/>

完成如上步骤以后,映射信息就已经全部完成了,下面就来创建一个测试类来测试使用Annotations注释是否成功完成映射。

会话(Session)的应用

1.Hibernate对象状态

一个实体类的实例可能处于三种不同状态中的一种,这三种状态分别是瞬时状态、持久状态、托管状态。下面来看这三种状态的详细说明。各状态转换提交得到其转换图如图所示。

Hibernate个人总结

2.使用save方法持久化对象

使用new关键字创建的对象并没有保存到数据库当中,这时的对象为瞬时状态,通过Session对象的save方法能够将其转换成持久状态,并同时在数据库表中添加相应记录。

save方法两有种重载形式,其代码如下。

public Serializable save(Object object) throws Hibernate Exception;

public Serializable save(String entityName, Object object) throws HibernateException;

其中Object参数用来设置实体类的实例名,entityName参数用来设置实体类的类名。我们通常只是用第一种重载形式的save方法。

3.使用saveOrUpdate方法持久化对象

使用save方法虽然能够完成对象的持久化,但是有时候容易出现问题,比如一个对象已经被持久化了,这时候再次调用save方法将抛出异常。使用saveOrUpdate方法可以很好的解决这一问题,它会自动判断该对象是否已经持久化,如果已经持久化了将执行更新操作,如果没有持久化才进行添加操作。

saveOrUpdate方法有两种重载形式,其代码如下。

public void saveOrUpdate(Object object) throws HibernateException;

public void saveOrUpdate(String entityName, Object object) throws HibernateException;

saveOrUpdate方法中的参数含义和save方法是完全一样的。

来设置实体类的类名。我们通常只是用第一种重载形式的save方法。

4.使用load方法装载对象

如果知道某个对象的持久化标识,就可以使用Session对象的load方法从数据库装载数据,使用load方法装载的对象是持久状态的。

load方法有五种重载形式,其代码如下。

public Object load(Class theClass, Serializable id) throws HibernateException;
public Object load(String entityName, Serializable id) throws HibernateException;
public void load(Object object, Serializable id) throws HibernateException;
public Object load(String entityName, Serializable id, LockMode lockMode) throws HibernateException;
public Object load(Class theClass, Serializable id, LockMode lockMode) throws HibernateException;

5.使用get方法装载对象

使用load方法虽然能够装载对象,但是如果装配的对象不存在,load方法仍然会返回一个持久对象该持久对象除了标识属性外,访问器其他属性或者方式时,都将抛出无法恢复的异常。这时可以使用get方法,当装配的对象不存在时将返回一个null值,这样就可以避免异常的出现。

get方法有四种重载形式,其代码如下。

public Object get(Class clazz, Serializable id) throws HibernateException;
public Object get(String entityName, Serializable id) throws HibernateException;
public Object get(String entityName, Serializable id, LockMode lockMode) throws HibernateException;
public Object get(Class clazz, Serializable id, LockMode lockMode) throws HibernateException;

6.使用refresh方法刷新对象

使用refresh方法能够根据数据库中的数据来刷新持久对象中的属性值。get方法有两种重载形式,其代码如下。

public void refresh(Object object) throws HibernateException;

public void refresh(Object object, LockMode lockMode) throws HibernateException;

其中object参数用来设置需要刷新的持久对象。

7.使用setFlushMode方法设置更新模式

当持久对象的属性值发送变化后,Hibernate会根据情况自动将这些更新的属性值进行持久化。那到底是在什么情况下会进行自动更新呢?可以通过getFlushMode方法来获得当前的更新模式,也可以通过setFlushMode方法来修改默认的更新模式。getFlushMode方法和setFlushMode方法代码如下。

public void setFlushMode(FlushMode flushMode);

public FlushMode getFlushMode();

其中flushMode参数用来设置更新模式,该参数有四个可选值,分别为FlushMode.MANUAL、FlushMode.COMMIT、FlushMode.AUTO、FlushMode.ALWAYS。

8.使用isDirty方法判断数据是否一致

有时候我们需要判断当前更新的持久对象和数据库中的数据是否保持一致,这时就可以Session对象的isDirty方法完成该判断。isDirty方法可以判断持久对象中的属性值是否和数据表中相应的字段的值保持一致。如果一致,返回false;否则,返回true。

9.使用delete方法删除记录

可以使用Session对象的delete方法来删除数据库中的记录。delete方法有两个重载形式,其代码如下所示。

public void delete(Object object) throws HibernateException;

public void delete(String entityName, Object object) throws HibernateException;

其中object参数用来指定需要删除的持久对象,entityName参数用来设置实体类的类名。

Hibernate高级映射和数据检索

在前面的章节中介绍了如何使用Hibernate配置映射,以及对对象的各种操作,如持久化、装载等等。在本章中将详细介绍如何进行Hibernate高级映射,包括关联关系映射和容器映射技术。还将介绍如果使用HQL来查询数据,包括HQL基础查询和高级查询。

重点内容:

多对一关系映射

一对多关系映射

一对一关系映射

使用标准查询API进行查询

使用HQL进行查询

关联关系映射

1.多对一关系映射

多对一的关系是类和类之间最常见的关系,比如在一个班级中,学生和班级就是多对一的关系,因为多个学生对应一个班级。班级和学生的关联关系图如图所示。

Hibernate个人总结

2.一对多关系映射

多个学生对应一个班级,所以学生和班级之间是多对一的关系。但是反过来一个班级中有多个学生,这时班级和学生之间是一对多的关系。

一个班级中要包含多个学生,那么在班级类中需要维护多个学生对象的引用,可以使用Set或者List来保存学生集合。修改班级类Classes.java,在该类中添加一个students的属性,用来保存多个学生记录。

3.一对一关系映射

一对一的关系也是类和类之间最常见的关系,比如一个人只有一个身份证信息,而一个身份证信息也只能对应一个人。其中人和身份证的一对一关联关系图如图所示。

Hibernate个人总结

标准查询API

1.查询所有记录

要使用标准查询API来完成查询操作,首先需要使用org.hibernate.Criteria接口。可以通过Session的createCriteria方法来创建一个Criteria实例对象。在Criteria中有一个list方法,通过该方法就可以返回查询到的所有记录。

Session session = HibernateSessionFactory.getSession();
Criteria crit = session.createCriteria(Fruit.class); List<Fruit> fruits = crit.list();
System.out.println("id\t" + "name");
for(Fruit fruit : fruits){
System.out.println(fruit.getId()+"\t"+fruit.getName());
}
HibernateSessionFactory.closeSession();

2.设置最大记录数

前面执行的查询所有记录,但是有时候我们并不需要查询所有所有的记录,而至需要部分的记录,这时就需要设置最大的记录数。在标准查询API中,可以通过使用Criteria实例对象的setMaxResults方法来设置返回的最大记录数。

Criteria crit = session.createCriteria(Fruit.class);
crit.setMaxResults(2);
List<Fruit> fruits = crit.list();

3.按条件查询

在进行查询时经常要使用到条件查询,比如查询名称为苹果的记录。在使用标准查询API进行查询时,可以使用Criteria接口的add方法为查询增加约束条件。每一个约束条件是一个org.hibernate.cri

terion.Criterion实例对象。可以通过由org.hibernate.criterion.
Restrictions类的静态方法获得相应的Criterion对象。
Criteria crit = session.createCriteria(Fruit.class);
crit.add(Restrictions.eq("name", "苹果"));
List<Fruit> fruits = crit.list();

4.使用通配符完成模糊查询

前面介绍的查询都是精确查询,但是有时需要进行模糊查询,如查询包含“果”这个字的所有水果。标准查询API中提供了两种方式来完成模糊查询,一种是使用通配符,一种是使用MatchMode。下面首先来介绍使用通配符的方式完成模糊查询。

Criteria crit = session.createCriteria(Fruit.class);
crit.add(Restrictions.like("name", "%果%"));
List<Fruit> fruits = crit.list();

5.使用MatchMode完成模糊查询

前面介绍了如何使用通配符来完成模糊查询,下面再来看如何使用MatchMode完成模糊查询。在MatchMode类中有四个静态常量分别用来指定四个不同的匹配策略。

◆ MatchMode.ANYWHERE:相当于“%查询关键字%”。

◆ MatchMode.START:相当于“查询关键字%”。

◆ MatchMode.END:相当于“%查询关键字”。

◆ MatchMode.EXACT:精确匹配,相当于“查询关键字”。

6.对查询结果进行排序

在查询记录时经常要对结果进行排序,包括升序排序和降序排序。在标准查询API中可以使用org.hibernate.criterion.Order类对查询结果进行排序。Order类中包含两个静态方法,分别为asc和desc,使用这两个方法能够按照指定的属性来分别进行升序排序和降序排序。这两个方法都返回一个Order对象,通过Criteria实例对象的addOrder方法即可将排序规则添加到Criteria。

Criteria crit = session.createCriteria(Fruit.class);/
crit.addOrder(Order.desc("id"));
List<Fruit> fruits = crit.list();

HQL基础查询

1.使用HQL查询所有记录

在使用HQL进行查询时,首先需要定义一个HQL语句,然后通过Sesion的createQuery方法创建一个Query对象,通过Query对象的list方法即可以获得查询记录。下面来看一个最简单的范例,通过HQL查询所有的雇员记录。

Session session = HibernateSessionFactory.getSession();
String hql = "from Employee";
Query query = session.createQuery(hql);
List<Employee> employees = query.list();
HibernateSessionFactory.closeSession();

2.使用Select子句返回指定属性信息

在实际应用中,可能不需要查询雇员的所有信息,比如只需要查询雇员编号、雇员姓名和进入公司的时间。这时候就需要使用Select子句,通过Select子句指定需要查询的属性信息。

如果使用了Select子句,那么返回的不再是封装了持久对象的List,而是返回封装各种信息的List。比如只查询一个属性,这时将返回List<Object>类型的List对象;如果查询多个属性,则返回返回List<Object[]>类型的List对象,在Object数组中封装了所有的属性信息。

String hql = "select id,name,joinTime from Employee";

Query query = session.createQuery(hql);

3.使用as关键字给实体类起一个别名

在前面都是通过From子句指定实体类类名来完成的查询,但是当实体类的类名很长时,这样使用就不方法了。这时可以通过as关键字来为类名起一个别名。

String hql = "select emp.id,emp.name,emp.joinTime from Employee as emp";

Query query = session.createQuery(hql);

4.使用Where子句指定查询条件

在查询记录时,经常要使用条件,从而进行按条件查询。在HQL中,只需要添加一个Where子句,并在Where子句中添加查询条件就能实现按条件查询。如果Where子句包含多个查询条件,可以在每个查询条件中间添加or或and这些逻辑运算符。

String hql = "select emp.id,emp.name,emp.joinTime from  Employee as emp where emp.id > 2 and id < 5";

Query query = session.createQuery(hql);

5.指定查询参数来完成查询

在前面指定查询条件时,该查询条件是一个固定值,而在实际开发中,该查询条件一般是动态的值。那如何来为查询条件动态赋值呢,这时可以使用查询参数来完成。HQL的查询参数同JDBC的查询参数类似,可以使用按位置和参数名两种来完成赋值,不同的是HQL使用“:参数名”来定义查询参数。

定义完查询参数后,需要为查询参数命名,这时可以通过Query实例对象的setXXX方法来完成,其中XXX表示为不同的查询参数类型。

String hql = "select emp.id,emp.name,emp.joinTime from Employee as emp where emp.id > :idmin and emp.id < :idmax";
Query query = session.createQuery(hql);
query.setInteger("idmin", 2);
query.setInteger("idmax", 4);
List<Object> employees = query.list();

6.指定查询起始位置和查询最大记录数

可以通过Query实例对象的setFirstResult方法来设置查询的起始位置,该方法接受一个int类型的值,用来指定起始位置。还可以通过Query实例对象的setMaxResults方法来设置查询最大记录数,该方法同样接受一个int类型的值,用来指定最大记录数。

String hql = "from Employee";
Query query = session.createQuery(hql);
query.setFirstResult(1);
query.setMaxResults(4);
List<Employee> employees = query.list();

HQL高级查询

1.使用HQL对查询结果进行排序

可以通过HQL的Order by子句对查询结果进行排序,Order by子句后紧跟字段名,如果有多个字段,中间使用逗号进行分隔。在字段名后设置排序方式,有asc和desc两个可选值,分别用来进行升序和降序排序。

String hql = "from Employee as emp order by emp.id desc";
Query query = session.createQuery(hql);
List<Employee> employees = query.list();

2.使用HQL对查询结果进行分组

可以通过HQL的Group by子句对查询结果进行分组,比如对公司雇员的男职工和女职工进行分组。在Group by子句后设置字段名,该字段为分组依赖字段名,比如在对男职工和女职工进行分组时,分组字段名应该为雇员性别。

String hql = "select emp.sex,count(*) from " +"Employee as emp group by emp.sex";
Query query = session.createQuery(hql);

3.使用HQL执行数据库内置函数

在数据库中一般都提供了一些函数供数据库开发人员使用,这些函数别称为内置函数。内置函数一般用于完成一些特定功能,比如可以通过avg函数来求得字段的平均值;通过sum函数来求得字段值总和;通过min函数来求得字段的最小值;通过max函数来求得字段的最大值;通过count函数求得字段的记录数。Hibernate提供了对数据库内置函数的支持,所以在HQL中可以直接数据库内置函数。

String hql = "select count(*) from Employee";
Query query = session.createQuery(hql);
String hql2 = "select avg(emp.age) from Employee as emp";
Query query2 = session.createQuery(hql2);
String hql3 = "select min(emp.age) from Employee as emp";
Query query3 = session.createQuery(hql3);