Hibernate Framework
简介:
Hibernate框架是一个全自动的ORM框架,它拥有强大的映射功能,提供了缓存机制、事务管理、拦截器机制、查询语句的多方面支持
本系列笔记可能会遇到的专业词汇有:
Framework, 框架,某一类问题的总体解决方案
ORM,
Object Relationship Mapping
, 对象关系映射DATABASE, 数据库,存储数据的一种方式
HQL,
Hibernate Query Language
, Hibernate查询语句Transaction, 事务,一组相关的操作
Session, 会话
本系列笔记包含如下的课程内容:
- Hibernate框架原理和开发流程
- 框架缓存机制
- 对象关系映射
- 框架提供的查询机制
- 基于底层的
SQL
查询机制 - 基于
HQL
查询机制 - 基于
Criteria
查询机制
- 基于底层的
Hibernate 查询体系
此章节重点讲解 Hibernate框架的查询体系
章节重点:
- HQL查询
- QBC查询
- SQL查询
- 调试
章节难点:
- Criteria查询
- HQL高级查询
Hibernate框架提供了一个抽象层次的查询体系,如下:
其中,最底层的SQL查询基本上就是JDBC级别的封装,而Criteria接口采用了面向对象的操作方式,程序员无需写任何的SQL或类SQL语句,直接通过方法来生成SQL语句,抽象层次较高。
HQL查询
HQL, 全称:Hibernate Query Language, Hibernate查询语句,它具备如下特性:
- 基于SQL语法;
- 面向对象的查询语言;
- 使用可命名参数;
- 提供更简单的分页查询操作;
- 如果有select *,则必须省略.
如:
1 | String hql = "from User as u where u.name like :name"; |
在Hibernate框架中,使用org.hibernate.Query 接口来执行HQL字符串,它是以面向对象的方式来陈述的查询接口
通过 Session 接口的 createQuery(String hql)方法,来获取一个Query实例
1 | String hql = "from Department"; //查询出所有的部门 |
Query接口的常用方法如下:
- list() 方法, 将查询的结果封装成一个List集合对象,不带泛型,需要强制类型转换
- uniqueResult() 方法,将查询的结果封装为单个对象,如果不存在,则返回null
- setParameter(String param, Object value) 方法,用来为hql中指定的动态参数设值
- setFirstResult(int first) 方法,设置本次查询的第一条记录的下标(初始值是0)
- setMaxResults(int max) 方法,设置本次查询最多返回max条数据
HQL原理
在开发时,程序员专注于面向对象的编辑 HQL 语句;
在运行时,Hibernate 自动将 HQL 翻译成相应的 SQL 并执行。
HQL语法
一个 HQL 语句可以包含关键字、目标、别名和函数。
- 关键字
- 由Hibernate规定,它具有特殊语义,HQL大部分关键字都来自于SQL。
- 比如: select、from、where等。
- 目标
- 是HQL处理的内容,它可以是类、id属性、普通属性和关系属性。
- 别名
- 是指向当前目标的引用,使用它可以在HQL访问当前的目标。
- 比如 :User u 、 u.name等。
- 函数
- 可以对某个目标实施某种运算或处理,比如求和,取最大值等。
- 比如: max(u.age),sum(emp.salary)等。
HQL结构
- from 关键字
- 表示查询指定的实体对象
- 如: from User as u 或 from User u 或 from User
- select 关键字
- select 语句决定了from语句中的哪些对象将出现在返回的结果集中,如果不使用select,结果集中将包含from语句列出的所有对象。
- 如: select c.name,c.address from Customer as c
- 如果需要排重,可以使用 distinct 关键字
- select 函数
- select 语句中可以使用函数,对某些属性统计并返回结果。
- 常用的函数有: count(…), avg(…),sum(…),min(…),max(…),与SQL中的基本一致。
- 如:select count(*) from Customer c
- 注意:以上都使用uniqueResult()方法获得,返回类型是Object,可以通过 debug 来确定数据类型
- where 关键字
- where关键字用来限定哪些对象将会包含在返回的列表中,通常使用”类名别名.属性名”的方法
- 如: from Customer c where c.name like ?
- 如: from Contact con where con.customer.name = ?
- 运算符
- 算数运算符
- +,-, *, /
- 比较运算符
- =,>=,<=,<>,!=,like,between,not between
- 逻辑运算符
- and, or, not
- 空运算符
- is null, is not null, is empty, is not empty
- 包含运算符
- in, not in, member of, not member of
- 算数运算符
- order by
- order by语句可以将返回的结果按照类的某个属性进行排序,可以使用asc或desc指定升序或降序,如果不写默认为asc。
- 如: from Contact con order by con.name
- 如: from Contact con order by con.age desc
- join fetch
- 使用 join fetch 可以让 Hibernate 在查询时也提取关联对象的信息,不要再进行延迟加载。
- 如:from Customer c
join fetch
c.contactSet where c.level > :level
常用的HQL案例
- 根据用户名来查询用户
from User as u where u.name = :name
- 根据客户名来查询订单
from Order as o where o.customer.name = :name
//使用了隐式关联 - 根据订单下单时间来查询订单
from Order as o where o.order_date between ? and ?
//order_date表示下单时间 - 查询出用户名及用户的角色名
select u.name, r.name from User as u join u.roles as r
//显示关联 - 根据用户名来查询属于此用户角色信息
select r from Role r join r.users u where u.name = :name
//使用select指定只查角色
以上都是常见的HQL语法,在HQL中,还支持子查询和投影查询
子查询
1 | //子查询的HQL案例 |
投影查询
1 | //使用select来投影指定的列,并且通过Hibernate特殊语法来封装成java对象 |
当然,你事先得编写一个视图类
CustView, 如下:
1 | package com.tz.view; |
HQL处理UPDATE和DELETE
语法: ( UPDATE | DELETE ) FROM? EntityName (WHERE where_conditions)?
好处:这种方式删除指定的记录比通过对象的方式删除要高效得多。
1 | //更新满足条件的客户名称 |
1 | //如果要更新版本的时间戳,则可以: |
1 | //删除操作 |
分页查询
分页查询很简单,无需我们编写底层的分页查询SQL,而只需要调用如下的方法即可
- setFirstResult(int first)
- setMaxResults(int max)
为什么要使用分页?
铁律一:
只要存在实体类的列表页面,通常都会做分页处理.
原因:
1)提高查询效率,只需查询一小部分数据;
2)优化用户体验,无需面对海量数据,就像翻书一样浏览数据。铁律二:
在分页基础上,还需提供搜索功能,进一步改善用户体验.
原因:
想象一个没有搜索功能的淘宝首页….
案例代码
1 | //分页显示图书信息,每页显示 10行, 如果要查第2页,则 |
以上的查询,生成的sql语句中,会根据不同的DB平台来生成分页的语法,而程序员们无需考虑底层的分页语法.
Criteria查询
org.hibernate.Criteria 是一个简单易用的,通过约束条件来进行查询的接口。可以轻松的解决类似搜索页面(其中存在N个搜索条件,且存在超过2的N次方的组合情况)的需求问题
通过Criteria接口进行查询,也叫 Query By Criteria, 简称QBC, 它是最高层次的查询抽象,程序员无需编写任何的查询字符串,而是采用方法调用来生成SQL。
通过 Session接口的 createCriteria(Class c) 来创建Criteria实例.
1 | //示例 |
Criteria原理
Hibernate 自动将 Criteria 翻译成相应的 SQL 并执行。
Criteria常用API
从上面的类图中可以看出,几个核心的接口和类是:
- Criterion 添加where条件的准则接口,通过Restrictions工厂类可以获取此接口的实例
- Restrictions 限制类,用来生成where条件
- Projection 添加投影查询、分组查询的接口,通过Projections工厂类可以获取此接口的实例
- Projections 工厂类,用来生成投影、分组的实例
- Order 排序类
其它的类型都是派生于Criterion接口和Projection接口
Criteria接口中有如下方法:
Restrictions类有如下方法:
Projections类有如下方法:
Order类有如下方法:
详情可以查看 [Criteria] 的在线API
详情可以查看 [Restrictions] 的在线API
详情可以查看 [Projections] 的在线API
详情可以查看 [Order] 的在线API
代码案例
1 | //统计客户总数 |
1 | //根据客户id来查询属于此客户的订单 |
1 | //动态多条件查询 |
子查询
在HQL中,可以使用子查询的语法,在Criteria查询中,也可以使用子查询,不过这里要引入另一个类:DetachedCriteria, 有关此类的详细说明,可以查看[DetachedCriteria] API
DetachedCriteria,也叫离线的Criteria,也就是此类的实例可以不由session进行创建,而利用Criteria的准则来构建SQL,待到要执行之时,再关联上session即可,所以,利用这个原理,可以实现子查询的功能。
下面,来看一下DetachedCriteria的API介绍和方法列表:
可以看出,这个类实现了CriteriaSpecification接口,而Criteria则是此接口的子接口,换句话说,CriteriaImpl类也实现了这个接口,所以,DetachedCriteria的操作方法与Criteria几乎一样。
案例
1 | //利用 DetachedCriteria构建一个“查询”: 平均订单费用 |
下面,给出 Property 类的API片断如下:
当然,DetachedCriteria 也可以单独使用,只是在调用时,必需要把它与session关联,这样才可以执行。
如:
1 | DetachedCriteria dc = DetachedCriteria.forClass(Customer.class,"c"); |
SQL查询
用来执行本地化的sql语句的接口,在Hibernate查询体系中,抽象的层次最低,但有较高的查询效率。
通过 Session.createSQLQuery(String sql) 来创建
1 | //基本例子 |
标量查询
1 | //查询客户的name,phone,id 三个列值 |
1 | //添加条件 |
实体查询
1 | //查询所有的客户 |
关联查询
1 | String sql = "select {o.*},{c.*} from hbm_order o, hbm_customer c where o.customer_id = c.id"; |
1 | String sql = "select {o.*},{c.*} from hbm_order o, hbm_customer c where o.customer_id = c.id"; |
本章小节
- 熟练掌握HQL的查询
- 熟练掌握Criteria的查询
- 了解SQLQuery的查询