hibernate框架

Hibernate框架的概述


什么是框架?

框架指的是软件的半成品,已经完成了部分功能。

企业中开发一般使用SSH(Struts2+Spring+Hibernate)和SSM(SpringMVC+Spring+MyBatis)。

Hibernate

Hibernate是一个轻量级的JDBC封装,使用Hibernate来完成原来使用JDBC完成的操作,也就是与数据库的交互操作。它是在Dao层去使用的。总而言之,Hibernate就是一个持久层的ORM框架

ORM思想

所谓的ORM就是利用描述对象和数据库表之间映射的元数据,自动把Java应用程序中的对象,持久化到关系型数据库的表中。通过操作Java对象,就可以完成对数据库表的操作。

学习重点

  1. 掌握Hiberate的关联映射——解决表与表之间存在的关系问题,有1:n(一对多)、 1:1(一对一)、m:n(多对多)关系;
  2. 掌握Hiberate的检索方式——即掌握Hiberate的查询;
  3. 掌握Hiberate的优化方式——即提高Hiberate的效率。

Hibernate5的使用

目录结构:

架构

Hibernate 架构是分层的,作为数据访问层,不必知道底层 API 。Hibernate 利用数据库以及配置数据来为应用程序提供持续性服务(以及持续性对象)。

下面是一个非常高水平的 Hibernate 应用程序架构视图。

image

下面是一个详细的 Hibernate 应用程序体系结构视图以及一些重要的类。

image

主要对象

配置对象

配置对象是在任何 Hibernate 应用程序中创造的第一个 Hibernate 对象,并且经常只在应用程序初始化期间创造。它代表了 Hibernate 所需一个配置或属性文件。配置对象提供了两种基础组件。

  • 数据库连接:由 Hibernate 支持的一个或多个配置文件处理。这些文件是 hibernate.propertieshibernate.cfg.xml
  • 类映射设置:这个组件创造了 Java 类和数据库表格之间的联系。

SessionFactory 对象

配置对象被用于创造一个 SessionFactory 对象,使用提供的配置文件为应用程序依次配置 Hibernate,并允许实例化一个会话对象。SessionFactory 是一个线程安全对象并由应用程序所有的线程所使用。

SessionFactory 是一个重量级对象所以通常它都是在应用程序启动时创造然后留存为以后使用。每个数据库需要一个 SessionFactory 对象使用一个单独的配置文件。所以如果使用多种数据库那么要创造多种 SessionFactory 对象。

Session 对象

一个会话被用于与数据库的物理连接。Session 对象是轻量级的,并被设计为每次实例化都需要与数据库的交互。持久对象通过 Session 对象保存和检索。

Session 对象不应该长时间保持开启状态因为它们通常情况下并非线程安全,并且它们应该按照所需创造和销毁。

Transaction 对象

一个事务代表了与数据库工作的一个单元并且大部分 RDBMS 支持事务功能。在 Hibernate 中事务由底层事务管理器和事务(来自 JDBC 或者 JTA)处理。

这是一个选择性对象,Hibernate 应用程序可能不选择使用这个接口,而是在自己应用程序代码中管理事务。

Query 对象

Query 对象使用 SQL 或者 Hibernate 查询语言(HQL)字符串在数据库中来检索数据并创造对象。一个查询的实例被用于连结查询参数,限制由查询返回的结果数量,并最终执行查询。

Criteria 对象

Criteria 对象被用于创造和执行面向规则查询的对象来检索对象。

需要的包/库

Hibernate 配置

Hibernate 需要事先知道在哪里找到映射信息,这些映射信息定义了 Java 类怎样关联到数据库表。Hibernate 也需要一套相关数据库和其它相关参数的配置设置。所有这些信息通常是作为一个标准的 Java 属性文件提供的,名叫 hibernate.properties。又或者是作为 XML 文件提供的,名叫 hibernate.cfg.xml

我们将考虑 hibernate.cfg.xml 这个 XML 格式文件,来决定在我的例子里指定需要的 Hibernate 应用属性。

Hibernate 属性

下面是一个重要的属性列表,可能需要表中的属性来在单独的情况下配置数据库。

S.N.属性和描述
1hibernate.dialect 这个属性使 Hibernate 应用为被选择的数据库生成适当的 SQL。
2hibernate.connection.driver_class JDBC 驱动程序类。
3hibernate.connection.url 数据库实例的 JDBC URL。
4hibernate.connection.username 数据库用户名。
5hibernate.connection.password 数据库密码。
6hibernate.connection.pool_size 限制在 Hibernate 应用数据库连接池中连接的数量。
7hibernate.connection.autocommit 允许在 JDBC 连接中使用自动提交模

案例:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
	
<hibernate-configuration>
	<session-factory>
		<!-- 下面是三个必须要有的配置 -->
		<!-- 配置连接MySQL数据库的基本参数 -->
		<property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate?useSSL=false&amp;allowPublicKeyRetrieval=true&amp;serverTimezone=UTC</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">123456</property>
		
		<!-- 配置Hibernate的方言 -->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		
		<!-- 下面两个是可选的配置 -->
		<!-- 打印sql语句 -->
		<property name="hibernate.show_sql">true</property>
		<!-- 格式化sql语句 -->
		<property name="hibernate.format_sql">true</property>
		<!--自动生成-->
    	<!-- <property name="hbm2ddl.auto">create</property> -->
		
		<!-- 告诉Hibernate的核心配置文件加载哪个映射文件 -->
		<mapping resource="com/gen/entity/Company.hbm.xml"/>
		<mapping resource="com/gen/entity/Staff.hbm.xml"/>
		<mapping resource="com/gen/entity/User.hbm.xml"/>
		<mapping resource="com/gen/entity/Role.hbm.xml"/>
	</session-factory>
</hibernate-configuration>
create启动时删数据库中的表,然后创建,退出时不删除数据表
create-drop启动时删数据库中的表,然后创建,退出时删除数据表 如果表不存在报错
update如果启动时表格式不一致则更新表,原有数据保留
validate项目启动表结构进行校验 如果不一致则报错

Hibernate会话

Session 用于获取与数据库的物理连接。 Session 对象是轻量级的,并且设计为在每次需要与数据库进行交互时被实例化。持久态对象被保存,并通过 Session 对象检索找回。

该 Session 对象不应该长时间保持开放状态,因为它们通常不能保证线程安全,而应该根据需求被创建和销毁。Session 的主要功能是为映射实体类的实例提供创建,读取和删除操作。这些实例可能在给定时间点时存在于以下三种状态之一:

  • 瞬时状态: 一种新的持久性实例,被 Hibernate 认为是瞬时的,它不与 Session 相关联,在数据库中没有与之关联的记录且无标识符值。

  • 持久状态:可以将一个瞬时状态实例通过与一个 Session 关联的方式将其转化为持久状态实例。持久状态实例在数据库中没有与之关联的记录,有标识符值,并与一个 Session 关联。

  • 脱管状态:一旦关闭 Hibernate Session,持久状态实例将会成为脱管状态实例。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K8wE5326-1616758005883)(C:\Users\ShiGen\AppData\Roaming\Typora\typora-user-images\image-20210216135000123.png)]

Hibernate使用

1.导入相应的jar包

2.创建实体类

package com.gen.entity;

import java.util.Set;

public class Company {
	private Integer cid;
	private String cname;
	private String nature;
	private Set<Staff> staffs;
//  省略get、set、toString方法

}

3.创建数据库、表

CREATE TABLE `company` (
		  `cid` int NOT NULL AUTO_INCREMENT,
		  `cname` varchar(255) DEFAULT NULL,
		  `nature` varchar(255) DEFAULT NULL,
		  PRIMARY KEY (`cid`)
		) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8

4.映射关系

①以格式 <classname>.hbm.xml保存映射文件
/Hibernate01/src/com/gen/entity/Company.hbm.xml
②引入xml的dtd约束
③配置映射
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
<hibernate-mapping>
	<!-- 建立类与表的映射 -->
	<class name="com.gen.entity.Company" table="company">
		<!-- 建立类中的属性与表中的主键相对应 -->
		<id name="cid" column="cid">
			<!-- 主键的生成策略,现在使用的是本地生成策略 自动增长 -->
			<generator class="native" />
		</id>
		
		<!-- 建立类中的普通属性和表中的字段相对应 -->
		<property name="cname" column="cname" />
		<property name="nature" column="nature" />
		<!-- cascade 级联操作时相应的对象的操作 -->
		<!-- inverse 外键维护在多的一方 -->
		
		<!-- name属性:集合属性名
        column属性:外键列名
        class属性:关联的对象完整类名 -->
		<set name="staffs" lazy="true" inverse="false" cascade="save-update,delete">
		<!-- 对方表里的外键列名 -->
			<key column="cid"></key>
			<one-to-many class="com.gen.entity.Staff"/>
		</set>
	</class>
</hibernate-mapping>
标签的使用
  • 映射文件是一个以 <hibernate-mapping> 为根元素的 XML 文件,里面包含所有<class>标签。
  • <class> 标签是用来定义从一个 Java 类到数据库表的特定映射。Java 的类名使用 name 属性来表示,数据库表明用 table 属性来表示。
  • <meta> 标签是一个可选元素,可以被用来修饰类。
  • <id> 标签将类中独一无二的 ID 属性与数据库表中的主键关联起来。id 元素中的 name 属性引用类的性质,column 属性引用数据库表名的列。type 属性保存 Hibernate 映射的类型,这个类型会将从 Java 转换成 SQL 数据类型。
  • 在 id 元素中的 <generator> 标签用来自动生成主键值。设置 generator 标签中的 class 属性可以设置 native 使 Hibernate 可以使用 identity, sequencehilo 算法根据底层数据库的情况来创建主键。
  • <property> 标签用来将 Java 类的属性与数据库表的列匹配。标签中 name 属性引用的是类的性质,column 属性引用的是数据库表的列。type 属性保存 Hibernate 映射的类型,这个类型会将从 Java 转换成 SQL 数据类型。

主键的生成策略

名 称描 述
increment用于 long.short 或 int 类型,由 Hibernate 自动以递增的方式生成唯一标识符,每次增量为 1。只有当没有其他进程向同一张表中插入数据时才可以使用,不能在集群环境下使用,适用于代理主键
identity采用底层数据库自身提供的主键生成标识符,条件是数据库支持自动增长数据类型。在 DB2、MySQL、SQL Server、Sybase 和 HypersonicSQL 数据库中可以使用该生成器,该生成器要求在数据库中把主键定义成为自增长类型,适用于代理主键
sequenceHibernate 根据底层数据库序列生成标识符。条件是数据库支持序列,适用于代理主键
hilo使用一个高/低位算法高效地生成 long、short 或 int 类型的标识符。给定一个表和字段(默认的表和字段分别为 hibernate_unique_key 和 next_hi)作为高位值的来源。高/低位算法产生的标识符仅在特定数据库中是唯一的
native根据底层数据库对自动生成标识符的能力选择 identity、sequence、hilo 三种生成器中的一种,适合跨数据库平台开发,适用于代理主键
uuidHibernate 采用 128 位的 UUID 算法生成标识符。该算法能够在网络环境中生成唯一的字符串标识符,其 UUID 被编码为一个长度为 32 位的十六进制字符串。这种策略并不流行,因为字符串类型的主键比整数类型的主键占用更多的数据库空间,适用于代理主键
assigned由 java 程序负责生成标识符,如果不指定 id 元素的 generator 属性,则默认使用该主键生成策略,适用于自然主键

属性

属性名说 明
name持久化类属性的名称,以小写字母开头
column数据表字段名
type数据表的字段类型
length数据表字段定义的长度
lazy指定当持久化类的实例首次被访问时,是否对该属性使用延迟加载,其默认值是 false
unique是否对映射列产生一个唯一性约束。常在产生 DDL 语句或创建数据库对象时使用
not-null是否允许映射列为空

Hibernate 映射类型

映射类型

当准备一个 Hibernate 映射文件时,我们已经看到把 Java 数据类型映射到了 RDBMS 数据格式。在映射文件中已经声明被使用的 types 不是 Java 数据类型;它们也不是 SQL 数据库类型。这种类型被称为 Hibernate 映射类型,可以从 Java 翻译成 SQL,反之亦然。

原始类型

映射类型Java 类型ANSI SQL 类型
integerint 或 java.lang.IntegerINTEGER
longlong 或 java.lang.LongBIGINT
shortshort 或 java.lang.ShortSMALLINT
floatfloat 或 java.lang.FloatFLOAT
doubledouble 或 java.lang.DoubleDOUBLE
big_decimaljava.math.BigDecimalNUMERIC
characterjava.lang.StringCHAR(1)
stringjava.lang.StringVARCHAR
bytebyte 或 java.lang.ByteTINYINT
booleanboolean 或 java.lang.BooleanBIT
yes/noboolean 或 java.lang.BooleanCHAR(1) (‘Y’ or ‘N’)
true/falseboolean 或 java.lang.BooleanCHAR(1) (‘T’ or ‘F’)

日期和时间类型

映射类型Java 类型ANSI SQL 类型
datejava.util.Date 或 java.sql.DateDATE
timejava.util.Date 或 java.sql.TimeTIME
timestampjava.util.Date 或 java.sql.TimestampTIMESTAMP
calendarjava.util.CalendarTIMESTAMP
calendar_datejava.util.CalendarDATE

二进制和大型数据对象

映射类型Java 类型ANSI SQL 类型
binarybyte[]VARBINARY (or BLOB)
textjava.lang.StringCLOB
serializableany Java class that implements java.io.SerializableVARBINARY (or BLOB)
clobjava.sql.ClobCLOB
blobjava.sql.BlobBLOB

JDK 相关类型

映射类型Java 类型ANSI SQL 类型
classjava.lang.ClassVARCHAR
localejava.util.LocaleVARCHAR
timezonejava.util.TimeZoneVARCHAR
currencyjava.util.CurrencyVARCHAR

Hibernate 注释

注释

Hibernate 注释是无需使用 XML 文件来定义映射的最新方法。额外使用注释或直接代替 XML 映射元数据。

Hibernate 注释是一种强大的来给对象和关系映射表提供元数据的方法。所有的元数据被添加到 POJO java 文件代码中,这有利于用户在开发时更好的理解表的结构和 POJO。

如果想让应用程序移植到其它 EJB 3 的 ORM 应用程序中,必须使用注释来表示映射信息,但是如果想要得到更大的灵活性,那么应该使用基于 XML 的映射。

Hibernate 注释的环境设置

首先必须确定使用的是 JDK 5.0,否则需要升级的 JDK 至 JDK 5.0,来使的主机能够支持注释。

其次,需要安装 Hibernate 3.x 注释包,可以从 sourceforge 行下载:下载 Hibernate 注释 并且从 Hibernate 注释发布中拷贝 hibernate-annotations.jar, lib/hibernate-comons-annotations.jarlib/ejb3-persistence.jar 到的 CLASSPATH。

注释类示例

正如我上面所提到的,所有的元数据被添加到 POJO java 文件代码中,这有利于用户在开发时更好的理解表的结构和 POJO。

下面我们将使用 EMPLOYEE 表来存储对象:

create table EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

以下是用带有注释的 Employee 类来映射使用定义好的 Employee 表的对象:

import javax.persistence.*;

@Entity
@Table(name = "EMPLOYEE")
public class Employee {
   @Id @GeneratedValue
   @Column(name = "id")
   private int id;

   @Column(name = "first_name")
   private String firstName;

   @Column(name = "last_name")
   private String lastName;

   @Column(name = "salary")
   private int salary;  

}

@Entity 注释

EJB 3 标准的注释包含在 javax.persistence 包,所以我们第一步需要导入这个包。第二步我们对 Employee 类使用 @Entity 注释,标志着这个类为一个实体 bean,所以它必须含有一个没有参数的构造函数并且在可保护范围是可见的。

@Table 注释

@table 注释允许明确表的详细信息保证实体在数据库中持续存在。

@table 注释提供了四个属性,允许覆盖的表的名称,目录及其模式,在表中可以对列制定独特的约束。

@Id 和 @GeneratedValue 注释

每一个实体 bean 都有一个主键,在类中可以用 @Id 来进行注释。主键可以是一个字段或者是多个字段的组合,这取决于的表的结构。

默认情况下,@Id 注释将自动确定最合适的主键生成策略,但是可以通过使用 @GeneratedValue 注释来覆盖掉它。strategygenerator 这两个参数我不打算在这里讨论,所以我们只使用默认键生成策略。让 Hibernate 确定使用哪些生成器类型来使代码移植于不同的数据库之间。

@Column Annotation

@Column 注释用于指定某一列与某一个字段或是属性映射的细节信息。可以使用下列注释的最常用的属性:

属性名说明默认值
unique可选,是否在该列上设置唯一约束false
nullable可选,是否设置该列的值可以为空false
insertable可选,该列是否作为生成的insert语句中的一个列true
updatable可选,该列是否作为生成的update语句中的一个列true
columnDefinition可选: 为这个特定列覆盖SQL DDL片段 (这可能导致无法在不同数据库间移植)比如我们想把Integer readNum 设为默认0,可使用此属性: INT DEFAULT 0
table可选,定义对应的表默认为当前类对应表
length可选,列长度255
precision可选,列十进制精度(decimal precision)0
scale可选,如果列十进制数值范围(decimal scale)可用,在此设置0

Hibernate一级缓存

Hibernate中的缓存分为一级缓存和二级缓存,这两个级别的缓存都位于持久化层,并且存储的都是数据库数据的备份。其中一级缓存是 Hibernate 的内置缓存。

一级缓存其实就是 Session 缓存。Session 缓存是一块内存空间,用于存储与管理 Java 对象。

在使用 Hibernate 查询对象时,首先会使用对象的 OID 值在 Hibernate 的一级缓存中查找,如果找到匹配的对象,则直接将该对象从一级缓存中取出使用;如果没有找到匹配的对象,则会去数据库中查询对应的数据。当从数据库中查询到所需数据时,该数据信息会存储到一级缓存中。由此可知,Hibernate 一级缓存的作用就是减少对数据库的访问次数。

Hibernate 的一级缓存具有如下特点。

1)当应用程序调用 Session 接口的 save()、update()、saveOrUpdate() 时,如果 Session 缓存中没有相应的对象,则 Hibernate 就会自动把从数据库中查询到的相应对象信息加入到一级缓存中。

2)当调用 Session 接口的 load()、get() 方法,以及 Query 接口的 list()、iterator() 方法时,会判断缓存中是否存在该对象,有则返回,不会查询数据库,如果缓存中没有要查询的对象,则再去数据库中查询对应对象,并添加到一级缓存中。

3)当调用 Session 的 close() 方法时,Session 缓存会被清空。

4)Session 能够在某些情况下,按照缓存中对象的变化,执行相关的 SQL 语句同步更新数据库,这一过程被称为刷出缓存(flush)。

在默认情况下,Session 在如下几种情况中会刷出缓存。

1)当应用程序调用 Transaction 的 commit() 方法时,该方法先刷出缓存(调用 session.flush() 方法),然后再向数据库提交事务(调用 commit() 方法)。

2)当应用程序执行一些查询操作时,如果缓存中持久化对象的属性已经发生了变化,会先刷出缓存,以保证查询结果能够反映持久化对象的最新状态。

3)调用 Session 的 flush() 方法。

Hibernate级联操作

一对多操作(公司与员工)

<hibernate-mapping>
	<!-- 建立类与表的映射 -->
	<class name="com.gen.entity.Company" table="company">
		<!-- 建立类中的属性与表中的主键相对应 -->
		<id name="cid" column="cid">
			<!-- 主键的生成策略,现在使用的是本地生成策略 自动增长 -->
			<generator class="native" />
		</id>
		
		<!-- 建立类中的普通属性和表中的字段相对应 -->
		<property name="cname" column="cname" />
		<property name="nature" column="nature" />
		<!-- cascade 级联操作时相应的对象的操作 -->
		<!-- inverse 外键维护在多的一方 -->
		
		<!-- name属性:集合属性名
        column属性:外键列名
        class属性:关联的对象完整类名 -->
		<set name="staffs" lazy="true" inverse="false" cascade="save-update,delete">
		<!-- 对方表里的外键列名 -->
			<key column="cid"></key>
			<one-to-many class="com.gen.entity.Staff"/>
		</set>
	</class>
</hibernate-mapping>
<hibernate-mapping>
	<!-- 建立类与表的映射 -->
	<class name="com.gen.entity.Staff" table="staff">
		<!-- 建立类中的属性与表中的主键相对应 -->
		<id name="sid" column="sid">
			<!-- 主键的生成策略,现在使用的是本地生成策略 自动增长 -->
			<generator class="native" />
		</id>
		
		<!-- 建立类中的普通属性和表中的字段相对应 -->
		<property name="sname" column="sname" />
		<property name="sex" column="sex" />
		<property name="cid" column="cid" insert="false" update="false"></property>
		
		<many-to-one name="company" class="com.gen.entity.Company" column="cid"></many-to-one>

	</class>
</hibernate-mapping>

多对多操作(用戶与角色)

		<set name="roles" table="user_role" cascade="save-update,delete" inverse="false">
			<key column="user_id"></key>
			<many-to-many class="com.gen.entity.Role" column="role_id"></many-to-many>
		</set>
		<set name="users" table="user_role">
			<key column="role_id"></key>
			<many-to-many class="com.gen.entity.User" column="user_id"></many-to-many>
		</set>

Hibernate 查询语言

查询语言

Hibernate 查询语言(HQL)是一种面向对象的查询语言,类似于 SQL,但不是去对表和列进行操作,而是面向对象和它们的属性。 HQL 查询被 Hibernate 翻译为传统的 SQL 查询从而对数据库进行操作。

建议尽可能的使用 HQL 语句,以避免数据库关于可移植性的麻烦,并且体现了 Hibernate 的 SQL 生成和缓存策略。

在 HQL 中一些关键字比如 SELECT ,FROM 和 WHERE 等,是不区分大小写的,但是一些属性比如表名和列名是区分大小写的。

FROM 语句

如果想要在存储中加载一个完整并持久的对象,将使用 FROM 语句。以下是 FROM 语句的一些简单的语法:

String hql = "FROM Employee";
Query query = session.createQuery(hql);
List results = query.list();

如果需要在 HQL 中完全限定类名,只需要指定包和类名,如下:

String hql = "FROM com.hibernatebook.criteria.Employee";
Query query = session.createQuery(hql);
List results = query.list();

AS 语句

在 HQL 中 AS 语句能够用来给的类分配别名,尤其是在长查询的情况下

String hql = "FROM Employee AS E";
Query query = session.createQuery(hql);
List results = query.list();

关键字 AS 是可选择的并且也可以在类名后直接指定一个别名,如下:

String hql = "FROM Employee E";
Query query = session.createQuery(hql);
List results = query.list();

SELECT 语句

SELECT 语句比 from 语句提供了更多的对结果集的控制。如果只想得到对象的几个属性而不是整个对象需要使用 SELECT 语句

String hql = "SELECT E.firstName FROM Employee E";
Query query = session.createQuery(hql);
List results = query.list();

值得注意的是 Employee.firstName 是 Employee 对象的属性,而不是一个 EMPLOYEE 表的字段。

WHERE 语句

如果想要精确地从数据库存储中返回特定对象,需要使用 WHERE 语句

String hql = "FROM Employee E WHERE E.id = 10";
Query query = session.createQuery(hql);
List results = query.list();

ORDER BY 语句

为了给查询结果进行排序,将需要使用 ORDER BY 语句。能利用任意一个属性给的结果进行排序,包括升序或降序排序。

String hql = "FROM Employee E WHERE E.id > 10 ORDER BY E.salary DESC";
Query query = session.createQuery(hql);
List results = query.list();

如果要给多个属性进行排序,只需要在 ORDER BY 语句后面添加要进行排序的属性即可,并且用逗号进行分割:

String hql = "FROM Employee E WHERE E.id > 10 " +
             "ORDER BY E.firstName DESC, E.salary DESC ";
Query query = session.createQuery(hql);
List results = query.list();

GROUP BY 语句

这一语句允许 Hibernate 将信息从数据库中提取出来,并且基于某种属性的值将信息进行编组,通常而言,该语句会使用得到的结果来包含一个聚合值。下面是一个简单的使用 GROUP BY 语句的语法:

String hql = "SELECT SUM(E.salary), E.firtName FROM Employee E " +
             "GROUP BY E.firstName";
Query query = session.createQuery(hql);
List results = query.list();

使用命名参数

Hibernate 的 HQL 查询功能支持命名参数。这使得 HQL 查询功能既能接受来自用户的简单输入,又无需防御 SQL 注入攻击

String hql = "FROM Employee E WHERE E.id = :employee_id";
Query query = session.createQuery(hql);
query.setParameter("employee_id",10);
List results = query.list();

UPDATE 语句

HQL Hibernate 3 较 HQL Hibernate 2,新增了批量更新功能和选择性删除工作的功能。查询接口包含一个 executeUpdate() 方法,可以执行 HQL 的 UPDATE 或 DELETE 语句。

UPDATE 语句能够更新一个或多个对象的一个或多个属性

String hql = "UPDATE Employee set salary = :salary "  + 
             "WHERE id = :employee_id";
Query query = session.createQuery(hql);
query.setParameter("salary", 1000);
query.setParameter("employee_id", 10);
int result = query.executeUpdate();
System.out.println("Rows affected: " + result);

DELETE 语句

DELETE 语句可以用来删除一个或多个对象

String hql = "DELETE FROM Employee "  + 
             "WHERE id = :employee_id";
Query query = session.createQuery(hql);
query.setParameter("employee_id", 10);
int result = query.executeUpdate();
System.out.println("Rows affected: " + result);

INSERT 语句

HQL 只有当记录从一个对象插入到另一个对象时才支持 INSERT INTO 语句。下面是使用 INSERT INTO 语句的简单的语法:

String hql = "INSERT INTO Employee(firstName, lastName, salary)"  + 
             "SELECT firstName, lastName, salary FROM old_employee";
Query query = session.createQuery(hql);
int result = query.executeUpdate();
System.out.println("Rows affected: " + result);

聚合方法

HQL 类似于 SQL,支持一系列的聚合方法,它们以同样的方式在 HQL 和 SQL 中工作,以下列出了几种可用方法:

S.N.方法描述
1avg(property name)属性的平均值
2count(property name or *)属性在结果中出现的次数
3max(property name)属性值的最大值
4min(property name)属性值的最小值
5sum(property name)属性值的总和

distinct 关键字表示只计算行集中的唯一值

String hql = "SELECT count(distinct E.firstName) FROM Employee E";
Query query = session.createQuery(hql);
List results = query.list();

使用分页查询

以下为两种分页查询界面的方法:

S.N.方法&描述
1Query setFirstResult(int startPosition) 该方法以一个整数表示结果中的第一行,从 0 行开始。
2Query setMaxResults(int maxResult) 这个方法告诉 Hibernate 来检索固定数量,即 maxResults 个对象。

使用以上两种方法,我们可以在我们的 web 或 Swing 应用程序中构造一个分页组件

String hql = "FROM Employee";
Query query = session.createQuery(hql);
query.setFirstResult(1);
query.setMaxResults(10);
List results = query.list();

Hibernate 标准查询

Hibernate 提供了操纵对象和相应的 RDBMS 表中可用的数据的替代方法。一种方法是标准的 API,它允许建立一个标准的可编程查询对象来应用过滤规则和逻辑条件。

Hibernate Session 接口提供了 createCriteria() 方法,可用于创建一个 Criteria 对象,使当应用程序执行一个标准查询时返回一个持久化对象的类的实例。

Criteria cr = session.createCriteria(Employee.class);  
List results = cr.list();  

对标准的限制

可以使用 Criteria 对象可用的 add() 方法去添加一个标准查询的限制。

Criteria cr = session.createCriteria(Employee.class);    
cr.add(Restrictions.eq("salary", 2000));    
List results = cr.list();  

以下是几个例子,涵盖了不同的情况,可按要求进行使用:

Criteria cr = session.createCriteria(Employee.class);

// To get records having salary more than 2000
cr.add(Restrictions.gt("salary", 2000));

// To get records having salary less than 2000
cr.add(Restrictions.lt("salary", 2000));

// To get records having fistName starting with zara
cr.add(Restrictions.like("firstName", "zara%"));

// Case sensitive form of the above restriction.
cr.add(Restrictions.ilike("firstName", "zara%"));

// To get records having salary in between 1000 and 2000
cr.add(Restrictions.between("salary", 1000, 2000));

// To check if the given property is null
cr.add(Restrictions.isNull("salary"));

// To check if the given property is not null
cr.add(Restrictions.isNotNull("salary"));

// To check if the given property is empty
cr.add(Restrictions.isEmpty("salary"));

// To check if the given property is not empty
cr.add(Restrictions.isNotEmpty("salary"));

可以模仿以下示例,使用逻辑表达式创建 AND 或 OR 的条件组合:

Criteria cr = session.createCriteria(Employee.class);

Criterion salary = Restrictions.gt("salary", 2000);
Criterion name = Restrictions.ilike("firstNname","zara%");

// To get records matching with OR condistions
LogicalExpression orExp = Restrictions.or(salary, name);
cr.add( orExp );

// To get records matching with AND condistions
LogicalExpression andExp = Restrictions.and(salary, name);
cr.add( andExp );

List results = cr.list();

分页使用标准

这里有两种分页标准接口方法:

序号方法描述
1public Criteria setFirstResult(int firstResult),这种方法需要一个代表的结果集的第一行的整数,以第 0 行为开始。
2public Criteria setMaxResults(int maxResults),这个方法设置了 Hibernate 检索对象的 maxResults

利用上述两种方法结合在一起,我们可以在我们的 Web 或 Swing 应用程序构建一个分页组件。以下是一个例子,利用它可以一次取出 10 行:

Criteria cr = session.createCriteria(Employee.class);
cr.setFirstResult(1);
cr.setMaxResults(10);
List results = cr.list();

排序结果

标准 API 提供了 org.hibernate.criterion.order 类可以去根据的一个对象的属性把的排序结果集按升序或降序排列。这个例子演示了如何使用 Order 类对结果集进行排序:

Criteria cr = session.createCriteria(Employee.class);
// To get records having salary more than 2000
cr.add(Restrictions.gt("salary", 2000));

// To sort records in descening order
crit.addOrder(Order.desc("salary"));

// To sort records in ascending order
crit.addOrder(Order.asc("salary"));

List results = cr.list();  

预测与聚合

标准 API 提供了 org.hibernate.criterion.projections 类可得到各属性值的平均值,最大值或最小值。Projections 类与 Restrictions 类相似,均提供了几个获取预测实例的静态工厂方法。

Criteria cr = session.createCriteria(Employee.class);

// To get total row count.
cr.setProjection(Projections.rowCount());

// To get average of a property.
cr.setProjection(Projections.avg("salary"));

// To get distinct count of a property.
cr.setProjection(Projections.countDistinct("firstName"));

// To get maximum of a property.
cr.setProjection(Projections.max("salary"));

// To get minimum of a property.
cr.setProjection(Projections.min("salary"));

// To get sum of a property.
cr.setProjection(Projections.sum("salary"));  

Hibernate 原生 SQL

如果使用数据库特定的功能如查询提示或 Oracle 中的 CONNECT 关键字,可以使用原生 SQL 数据库来表达查询。Hibernate 3.x 允许为所有的创建,更新,删除,和加载操作指定手写 SQL ,包括存储过程。
应用程序会在会话界面用 createSQLQuery() 方法创建一个原生 SQL 查询:

public SQLQuery createSQLQuery(String sqlString) throws HibernateException

当通过一个包含 SQL 查询的 createsqlquery() 方法的字符串时,可以将 SQL 的结果与现有的 Hibernate 实体,一个连接,或一个标量结果分别使用 addEntity(), addJoin(), 和 addScalar() 方法进行关联。

标量查询

最基本的 SQL 查询是从一个或多个列表中获取一个标量(值)列表。以下是使用原生 SQL 进行获取标量的值的语法:

String sql = "SELECT first_name, salary FROM EMPLOYEE";
SQLQuery query = session.createSQLQuery(sql);
query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List results = query.list();

实体查询

以上的查询都是关于返回标量值的查询,只是基础性地返回结果集中的“原始”值。以下是从原生 SQL 查询中通过 addEntity() 方法获取实体对象整体的语法:

String sql = "SELECT * FROM EMPLOYEE";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(Employee.class);
List results = query.list(); 

指定 SQL 查询

以下是从原生 SQL 查询中通过 addEntity() 方法和使用指定 SQL 查询来获取实体对象整体的语法:

String sql = "SELECT * FROM EMPLOYEE WHERE id = :employee_id";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(Employee.class);
query.setParameter("employee_id", 10);
List results = query.list();  

[^designed by Gen 2-16-20]: Hibernate 框架

量查询

最基本的 SQL 查询是从一个或多个列表中获取一个标量(值)列表。以下是使用原生 SQL 进行获取标量的值的语法:

String sql = "SELECT first_name, salary FROM EMPLOYEE";
SQLQuery query = session.createSQLQuery(sql);
query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List results = query.list();

实体查询

以上的查询都是关于返回标量值的查询,只是基础性地返回结果集中的“原始”值。以下是从原生 SQL 查询中通过 addEntity() 方法获取实体对象整体的语法:

String sql = "SELECT * FROM EMPLOYEE";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(Employee.class);
List results = query.list(); 

指定 SQL 查询

以下是从原生 SQL 查询中通过 addEntity() 方法和使用指定 SQL 查询来获取实体对象整体的语法:

String sql = "SELECT * FROM EMPLOYEE WHERE id = :employee_id";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(Employee.class);
query.setParameter("employee_id", 10);
List results = query.list();  

[^designed by Gen 2-16-20]: Hibernate 框架

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值