Hibernate入门
1.框架:
概念:框架是一个提供了可重用的公共结构的半成品
主流框架:
1.Struts:最早的JAVA开源框架之一,是MVC设计模式的一个优秀体现,通过采用Java Servlet/JSP技术实现了基于J2EE Web应用的MVC设计模式的应用框架
2.Struts2:核心:WebWork 吸收了Struts1 的部分优点,提供了一个更加整洁的MVC设计模式实现的Web应用程序框架。引入了几个新的框架特性
3.Hibernate:一个优秀的持久化框架,负责简化将对象数据保存到数据库中,或从数据库中读取并封装数据的工作。
4.Spring:一个开源的 轻量级的框架 主要使现有的J2EE技术更容易使用和促进良好的编码习惯,主要作为依赖注入容器和AOP实现并存,提供声明式事务到DAO的支持简化开发的功能。
2.Hibernate介绍和环境搭建
(1)数据持久化
数据持久化是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中的数据模型的统称。 例如文件的读取,数据的存储都是数据持久化操作。
数据模型可以是任何数据结构或对象模型,存储模型可以是关系模型、XML、二进制流等。
(2)Hiebrnate框架和ORM
1.Hibernate 框架:Hibernate是数据持久化工具,是一个开放源代码的对象关系映射框架。Hibernate内部封装了通过JDBC访问数据库的操作,向上层应用提供面向对象的数据访问API。
2.ORM:对象关系映射。一种数据持久化技术。它在对象模型和关系型数据库之间建立起对应关系,并提供了一种机制,通过JavaBean对象去操作数据库表中的数据。
(3)Hibernate的优缺点以及适用场合
Hibernate框架的优点:
1.Hibernate功能强大,是Java应用与关系数据库之间的桥梁,较之JDBC方式操作数据库,代码量大大减少,提高了持久化代码的开发速度,降低了维护成本。
2.Hibernate支持许多面向对象的特性,如组合、继承、多态等,使得开发人员不必在面向业务领域的对象模型和面向数据库的关系数据模型之间来回切换,方便开发人员进行领域驱动的面向对象的设计与开发。
3.可移植性好
4.框架开源免费,可以在需要时研究源代码,改写源代码,进行功能的定制,具有可扩展性。
5.Hibernate适用于大中型项目。
创建持久化类和映射文件
持久化类是指其实例状态需要被Hibernate持久化到数据库的类。
3.使用Hibernate完成持久化操作
Hibernate操作数据库包括7个步骤:
1.读取并解析配置文件
2.读取并解析映射文件,创建SessionFactory对象。
3.打开Session
4.开始一个事务(增删改操作必须,查询操作可选)
5.数据库操作
Session.save(user);
6.结束事务
Tx.commit();//提交事务
tx.Rollback();//回滚事务
7.关闭Session
4.Hibernate中JAVA对象的三种状态
(1)瞬时状态
New创建对象后,对象并没有立刻持久化,并没有与数据库中的数据有任何关联,此时Java对象的状态为瞬时状态。
(2)持久状态
当对象与Session关联,被Session管理时,它就处于持久状态。持久状态的对象拥有数据库标识(数据库中的主键值)。
(3)游离状态
处于持久化状态的对象,脱离与其关联的Session的管理后,对象就处于游离状态。
三种状态之间的转换
1.瞬时状态转换为持久状态:Session的save OR Update() get() OR load()
2.持久状态转换为瞬时状态:Session.Delete()
3.持久状态转换为游离状态:Session.Close() .evict() .clear()
4.游离状态转换为持久状态:重新获取Session session.update() .saveOrUpdate()
5.游离状态转换为瞬时状态:Session.Delete()
5.脏检查及刷新缓存机制
在Hibernate中,状态前后发生变化的对象称为脏数据。
当Session缓存中对象的属性发生变化时,Session不会立即刷新和执行相关SQL语句,而是在特定的时间点才会刷新缓存。多条数据合并为一条数据一起提交SQL,大大减少了访问数据库的次数,从而提高程序的数据访问性能。
(1)当应用程序调用Transaction() 的COMMIT()时,Commit先调用Session的flush(),然后再向数据库提交事务。
(2)当应用程序显式调用Session.flush()时,刷新缓存。
6.更新数据的方法
(1)update():用于对游离状态的对象进行数据库更新操作。
(2)saveOrUpdate(): 对象是瞬时状态 调用 save 游离状态 调用Update
(3)Merge():把一个游离状态对象的属性复制到一个持久化对象中,
05——HQL
1.使用HQL查询语句
Hibernate支持三种查询方式:HQL查询 Criteria查询 和 原生SQL 查询
HQL(Hibernate Query Language)查询:HQL查询是一种面向对象的查询语句,没有表和字段的概念,只有类、对象和属性的概念。
Criteria查询:Criteria查询又称为对象查询,采用面向对象的方式构造查询。
原生SQL(Native SQL)查询:原生SQL查询就是直接执行SQL语句,可以在SQL中利用不同数据库所特有的一些特性进行查询。
三者比较:
HQL语句查询功能强大,能满足实际开发中的各种查询要求,HQL查询在形式上和SQL查询相似,但是不要被语法结构上的相似所迷惑,HQL查询是完全面向对象的,可以理解继承多态和关联之类的概念。
(1)编写HQL查询语句
1.from 子句
2.Select子句
3.Where 子句
4.使用表达式
5.Order by子句
(2)执行HQL语句
//声明并初始化
//构建Query对象
Query对象构建好之后,执行查询语句,并获取查询结果,有两种方式执行查询:
1.Query.List()
2.Query.iterator()
2.在HQL查询语句中绑定参数
1.参数绑定形式
a) 按参数位置绑定
在HQL查询语句中用“?”占位符来定义参数的位置。
Query query = session.createQuery(“from Emp where job=? And salary>?”);
Query对象提供了绑定各种类型的参数的方法,如果参数为字符串类型,可以调用setString() 整型:setinteger() 以此类推。
b) 按参数名称绑定
在HQL查询语句中定义命名参数,命名参数以“:”开头。
2.绑定各种类型的参数
Query接口提供了绑定各种数据类型的参数的方法。
SetBoolean():绑定类型为:java.lang.Boolean的参数
setByte():绑定类型为:java.lang.Byte的参数
setDouble():绑定类型为:java.lang.Double的参数
setDate():绑定类型为:java.util.Date的参数
setString():绑定类型为:java.lang.String的参数
除了以上用于绑定特定类型参数的方法外,Hibernate还提供了2个特殊的参数绑定方法:
1.SetParameter():绑定任意类型的参数
2.SetProperties():绑定命名参数与一个对象的属性值。
3.实现动态查询
4.使用uniqueResult()方法获取唯一结果
Hibernate的参数绑定机制,HQL参数绑定的两种形式:
1.按参数名字绑定即命名参数,建议使用命名参数的形式。
2.按参数位置绑定即使用占位符,构建复杂的动态查询时,可以使用占位符的形式,但是建议使用Criteria查询。
3.分页和投影
(1)实现数据分页查询
具体步骤:
1.使用聚合函数count()获得总记录数count。
2.计算总页数:
Int totalPages = (count% pagesize ==0)?(count/pagesize):(count/pagesize+1)
Pagesize:保存每页显示记录数
3.实现分页:
query.setFirstResult((pageIndex-1)*pageSize);
query.setMaxResult(pagesize);
List result = query.list();
(2)使用投影查询:
需要使用HQL的Select子句,投影查询有以下三种方式:
1.将每条查询结果封装成Object对象。
2.将每条查询结果封装成Object数组。
3.将每条查询结果通过构造函数封装成对象。
HQL支持投影查询、参数查询、分页查询等功能
4.使用MyEclipse反向工程工具
添加Hibernate能力 做反向映射。
06——Hibernate的关联映射
1.关联关系
在软件开发中,类与类之间最普遍的关系就是关联关系,而且关联是有方向的。
2.建立多对一的单向关联关系
(1)配置单向多对一关联
(2)实现增删改操作
3.建立一对多的双向关联关系
配置双向一对多关联
双向关联下的增删改操作
1.cascade属性 :none (默认) save-update delete all
2.<set>元素的inverse属性
3.<set>元素的Order by属性
4.建立多对多关联关系
配置单向多对多关联
配置双向多对多关联
实现增删改查操作
5.延迟加载
类级别的默认加载策略是延迟加载。
1.立即加载两大不足:
(1)Select语句的数目太多,需要频繁的访问数据库,影响查询性能。
(2)多余的加载对象操作,浪费许多内存空间。
延迟加载:Lazy属性
类级别:
<class>元素中的Lazy属性默认为true 可选值:true(延迟加载)false(立即加载)
一对多关联级别:
<set>元素中的Lazy属性可选值:true(延迟加载) false(立即加载)extra(增强延迟加载)
多对一关联级别:
<many-to-many> 元素中的Lazy属性可选值:proxy(延迟加载)、no-proxy(无代理延迟加载)、false(立即加载)、
<many-to-many>元素中中的Lazy属性默认为proxy(立即加载)
2.一对多和多对多关联的查询策略
<set>元素的Lazy属性 默认为true
True:延迟加载
False:立即加载
Extra:增强延迟加载
3.多对一关联的查询策略
设置多对一关联的查询策略
Lazy属性(默认为proxy)
Proxy:延迟加载
No-proxy:无代理延迟加载
False:立即加载
<set>节点的inverse属性描述了由哪一方负责维系关联关系;cascade属性描述了级联操作的规则。
LazyInitializationException 异常
4.Open Session in view 策略
07——Hibernate性能优化
1.映射一对多关联
Hibernate提供了两种映射一对一关联关系的方式:按照外键映射和按照主键映射
(1)按照外键映射
Unique默认值为false ;true :表达对象之间的一对一关联关系
Property-ref=“对象”
(2)按照主键映射
Constrained=“true”
对象标识符(OID :Object Identifier)使用foreign
2.组件的映射
3.Hibernate 缓存
Hibernate的缓存一般分为三类:
(1)Hibernate一级缓存:Session缓存称为一级缓存。Session的生命周期对应一个数据库的事务,所有Session的缓存是事务范围的缓存。一级缓存是必须的,持久化类的每个实例都具有唯一的OID
一级缓存作用:
1.减少访问数据库频率,提高数据库访问性能
2.保证数据库中的相关记录和缓存中的相应对象同步。
Session.save() update() saveOrUpdate() load() get()
调用Query.list() Iterator()
Session为应用程序提供了两个管理缓存的方法:
1.evcit():从缓存中清除指定的持久化对象
2.Clear():清空缓存中所有持久化对象。
3.Flush():用于强制进行从缓存到数据库的同步。
一级缓存随着Session的开启而产生,随Session的关闭而结束。
(2)Hibernate二级缓存
二级缓存是进程或群范围内的缓存,可以被所有SessionFactory共享,生命周期和SessionFactory一样,二级缓存是可配置插件。
Hiebrnate支持的缓存插件:
EHCache:支持 进程范围的缓存:内存或硬盘
OSCache:支持 进程范围的缓存:内存或硬盘
SwarmCache:不支持 集群范围的缓存
JBossCache:支持 集群范围的缓存
SessionFactory缓存分为内置缓存和外置缓存
内置缓存:Hibernate自带的,不可卸载,只读用来存放映射元数据和预定义SQL语句
外置缓存:一个可配置的缓存插件,默认SessionFactory不会启用,外置缓存中的数据是数据库数据的复制。
SessionFactory的外置缓存称为Hibernate的二级缓存,由SessionFactory负责管理,生命周期与整个应用程序的进程相对应,可选,可以在每个类、每个集合的粒度上配置二级缓存
配置二级缓存的步骤:
1.选择合适的缓存插件,配置其自带的配置文件
2.选择需要使用的二级缓存的持久化类,设置它的二级缓存的并发访问策略。
二级缓存并非适用所有场合,使用不当,反而会降低性能。
符合使用二级缓存的条件:
(1)很少修改的数据
(2)不是很关键的数据,能容忍短时间内读到过期数据
(3)不会在多个应用之间共享的数据
(4)应用参考的常量数据
不适应二级缓存:
(1)经常修改的数据
(2)财务数据,绝对不允许读到过期数据
(3)与其他应用共享的数据
(3)Hibernate查询缓存
步骤:
1.在Hibernate.cfg.xml中开启查询缓存
<property name=”hibernate.cache.use_query_cache”>true</property>
2.在程序中启用查询缓存:
query.setCacheable(true);
4.HQL连接查询
(1)各种连接查询
所有连接均适用于有关联关系的持久化类,并且在映射文件中对这种关联关系做了映射。
内链接: inner join 、join
迫切内链接:Inner join fetch 、 join fetch
左外连接:left outer join 、 left join
迫切左外连接:left outer join fetch 、left join fetch
右外连接:right outer join 、 right join
1.内连接
2.隐式内连接
3.外连接
4.交叉连接
交叉连接适用于两个类之间没有定义任何关联时。在where 子句中通过属性作为筛选条件。
(2)查询性能优化
1.Hibernate主要从以下几方面来优化查询性能
(1)使用迫切左外连接或迫切内连接查询策略,查询缓存等方式,减少Select语句的数目,降低访问数据库的频率
(2)使用延迟查询策略等方式避免加载多余的不需要访问的数据。
(3)使用Querty接口的Iterator()减少Select语句中的字段,从而降低访问数据库的访问量。Query接口的Iterator()和List()都用来执行SQL查询语句,在某些情况下,Iterator()能提高查询性能。
2.HQL优化
HQL优化是Hibernate程序性能优化的一方面,HQL语法与SQL语法非常相似,HQL是基于SQL的,只是增加了面向对象的封装。抛开HQL同Hibernate本身一些缓存机制的关联HQL的优化技巧一样。
在编写HQL语句时需要注意一下原则:
(1)避免OR操作的使用不当 无索引 导致全表扫面
(2)避免使用NOT 如果where子句包含NOT 执行该字段会导致索引失效。
(3)避免LIKE的特殊形式 前模糊: like % like_ 该字段索引不起作用。
(4)避免HAVING子句 HAVING是在检索所有记录后才对结果集进行过滤。 开销较大。
(5)避免使用Distinct 指定Distinct会导致在结果中删除重复的行,会对处理造成一定的影响, 所以在不要求 或 允许冗余时 尽量不要使用Distinct
(6)索引在以下情况下会失效,应注意使用:
> 只要对字段使用韩式,该字段的索引将不起作用, 如:subString(aa,1,1) =”xx”
> 只要对字段进行计算,该字段的索引将不起作用, price+10.
5.批量处理数据
Hibernate提供以下方式进行批量处理数据:
1.使用HQL进行批量操作
2.使用JDBC API进行批量操作
3.使用Session进行批量操作
(1)使用HQL进行批量操作
a) 批量插入数据
Insert into
b) 批量更新数据
Update Session.CREATEQUery() .executeUpdate()
c) 批量删除数据
Delete Session.CREATEQUery() .executeUpdate()
(2)使用Session进行批量操作
Hibernate提供的三种批量处理数据的方式,在实际开发中根据具体业务情况选择相应方式:进行对比
(1)JDBC API批量操作方式最灵活,可以在SQL中使用不同数据库自身的一些特性。
(2)HQL批量操作方式是跨数据库的,HQL语言是面向对象的,但有一定局限性,只能用于单个持续化类,不支持连续,不能使用子查询。
(3)Session批量操作方式把关系数据库加载到内存后再进行操作,适用于需要通过代码处理复杂的业务逻辑的情况。
08——Hibernate数据操作技巧
1.分组统计数据
HQL和SQL一样,使用Order By 关键字对数据分组,使用Having关键字对分组数据设定约束条件,从而完成对数据库的分组和统计。
(1)聚合函数
聚合函数通常被用来实现数据统计功能。
1.count():统计记录条数
2.Sum():求和
3.Min():求最小值
4.Max():求最大值
5.Avg():求平均值
HQL查询语句很灵活,它提供了SQL常用的几乎所有功能,可以利用Select子句同时查询多个聚合函数的结果。
HQL查询语句可以返回各种类型的查询结果(Object[]对象数组)
(2)分组查询
HQL查询语句使用group by 子句进行分组查询,使用Having子句筛选分组结果。
2.子查询
子查询语句应用在HQL查询语句的where子句中。
(1)子查询关键字
All(子查询语句返回所有记录) any (子查询语句返回任意一条记录)some (和any 意思相同)in(与=any意思相同) exists(子查询语句至少返回一条记录)
(2)操作集合的函数或属性
操作集合的函数或属性
Size() 或 Size :获得集合中元素的数目
MinIndex() 或 minIndex:对于建立索引的集合,获得最小的索引
MaxIndex() 或 maxIndex:对于建立索引的集合,获得最大的索引
MinElements()或minElements:对于包含基本类型元素的集合,获得集合中取值最小的元素
MaxElements()或maxElements:对于包含基本类型元素的集合,获得集合中取值最大的元素
Elements() 获得集合中的所有元素
3.原生SQL查询和命名查询
使用HQL查询时,Hibernate会生成标准的SQL查询语句,适用于所有的数据库平台。因此HQL是跨数据库平台的。
(1)原生SQL查询
SQLQuery接口还提供了addUoin()方法用于连接查询
(2)命名查询
Hibernate支持在映射文件中定义字符串形式的查询语句,这样的查询语句称为命名查询语句。
<sql-query> <return>
Session.getNamedQuery()获得查询语句。
4.BLOB和CLOB类型
(1)映射方法
Oracle中有两种大对象数据类型:
BOLB:二进制大对象
CLOB:字符串大对象
大对象类型映射
JAVE数据类型: Oracle数据类型
Byte[] BLOB
java.lang.String CLOB
java.sql.Clob CLOB
java.sql.Blob BLOB
1.字符串大对象声明为java.lang.String 类型,二进制大对象声明为byte[]类型
2.字符串大对象声明为java.sql.Clob类型,二进制大对象声明为java.sql.Blob类型
09——Criteria查询及注解
1.使用Criteria查询数据
(1)条件查询
使用Criteria查询包括一下步骤:
1.使用Session.createCriteria()方法创建Criteria。
2.使用Restrictions类提供静态方法设置查询条件,返回Criteria对象,一个Criteria对象代表一个查询语句,Criteria对象的add()方法用来添加查询条件。
3.使用Criteria接口的.list()方法来执行查询语句。List中的每个元素都是持久化对象。
HQL和Criteria支持的比较运算
=:SimpleExpression Restrictions.eq(String property Name,Object value)
>:SimpleExpression Restrictions.gt(String property Name,Object value)
<:SimpleExpression Restrictions.It(String property Name,Object value)
>=:SimpleExpression Restrictions.ge(String property Name,Object value)
<=:SimpleExpression Restrictions.Ie(String property Name,Object value)
<>:SimpleExpression Restrictions.ne(String property Name,Object value)
Is null::SimpleExpression Restrictions.isNull(String property Name,Object value)
Is not null::SimpleExpression Restrictions.inNotNull(String property Name,Object value)
HQL和Criteria支持的范围运算
In (列表):等于列表中的某一个值
Not In:不等于列表中的任意一个值
Between 值1and值2: 大于等于1小于等于2
Not Betweern and:小于1或大于2
HQL和Criteria支持的字符串模式匹配
Like 字符串模式匹配
iLike :忽略大小写。
Hibernate 提供了MatchMode类,该类中定义了静态常量,用于字符串模式匹配。
MatchMode.Start
Restrictions.like(“EMPName”,“s”,MatchMode.Start ) 以S 开头
MatchMode.end(“EMPName”,“s”,MatchMode.Start ) 以S结尾
MatchMode.anywhere() 包含“S”
MatchMode.EXACT() 表里等于“S” 精确匹配
HQL和Criteria支持的逻辑运算
AND:与
Or:或
NOT :非
HQL和Criteria支持的集合运算
Is empty:集合为空,不包含任何元素
Is not empty:集合不为空
动态查询:
对比HQL和Criteria的动态查询,HQL尽管支持生成动态查询语句,但是编程比较麻烦,Criteria查询适合于生成动态查询语句。
2.排序、分页及关联
(1)排序:HQL和Criteria都支持对查询结果排序,HQL使用Order by 子句对查询结果排序,Criteria查询使用org.hibernate.criterion.Order类对查询结果进行排序。
(2)分页查询:
SetFirstResult() :设置从那一个对象开始查询。
SetMaxResult():设置一次最多查询出的个数。
Hibernate生成的SQL语句使用Oracle的rownum关键字
分页具体步骤:
(1)使用Projections.count()方法获得总记录数count。
(2)计算总页数
Int pageSize =3; //每页显式的记录数
//计算总页数
Int totalpages =(count %pageSize ==0) ?(count /pageSize) :(count /pageSize+1)
(3)实现分页语句
Int pageIndex =1; 当前页号
Criteria.setFirstResult((pageSize-1)*pageSize);
Criteria.setMaxResult(pageSize);
List result = Criteria.list(); 得到当前页的查询结果。
(3)查询唯一对象
Query和Criteria接口执行查询语句的方法
List list(): 支持
Iterator iterate(): 支持
Object uniqueResult() 支持
Criteria接口不支持Iterator方法查询语句
(4)连接查询
Criteria查询和HQL查询都支持连接查询
Criteria只迟滞内链接和迫切左外连接, Criteria提供了createCriteria() 和createAlias()方法建立内连接。
Criteria查询还支持迫切左外连接,Criteria接口提供了setFetchMode()方法来设置迫切左外连接。
3.投影、分组及DetachedCriteria
Hibernate提供了org.hibernate.criterion.Projection接口和
org.hibernate.criterion.Projections类来支持投影。
Projections类是用来构建Projection对象的工厂类。通过调用Criteria接口的SetProjections()方法来设置投影属性。
在Criteria中使用投影来实现分组统计功能
org.hibernate.criterion.Projections类提供了使用聚合函数查询的方法
org.hibernate.criterion.Projections.groupProperty() 分组
org.hibernate.criterion.Projections.rowCount( ) 统计记录数
org.hibernate.criterion.Projections.avg() 统计平均值
org.hibernate.criterion.Projections.max() 统计最大值
org.hibernate.criterion.Projections.min() 统计最小值
org.hibernate.criterion.Projections.count() 统计某一字段的非空记录数
Sum(): 针对某一字段求和
使用DetachedCriteria
DetachedCriteria类和Criteria接口功能相似,他们分别实现和继承了CriteriaSpecification接口和Criteria与DetachedCriteria均可使用Criterion与Projection设置查询条件,但两者的创建形式不同。
(1)Criteria由Session对象创建。
(2)DetachedCriteria创建时不需要Session对象。
Hibernate支持DetachedCriteria
DetachedCriteria查询:在常规的Web编程中,有大量的动态条件查询,用户在网上自由选择某些条件,程序根据用户选择的条件,动态生成SQL语句,进行查询。针对这种需求,对应分层应用程序来说,Web层需要传递一个查询条件列表给业务层,业务层对象获得这个条件列表后,依次取出条件构造查询语句。
4.注解
(1)Hibernate提供了Hibernate Annotations扩展包,使用注解完成映射
使用Hibernate注解的步骤如下:
1.添加jar包
2.使用注解配置持久化类以及对象关联关系
3.使用AnnotationConfiguration建立SessionFactory
4.在Hibernate配置文件(hibernate.cfg.xml)中声明持久化类
(2)注解——配置持久化类
注解 含义和作用
@Entity 将一个类声明为一个持久化类
@Id 声明了持久化类的标识属性
@GeneratedValue 定义标识属性值的生成策略
@Table 为持久化类映射指定表
@Column 将属性映射到列(字段)
@Transient 将忽略这些属性
(3)注解——配置关联关系
注解 含义和作用
@OneToOne 建立持久化类之间的一对一关联关系
@OneToMany 建立持久化类之间的一对多关联关系
@ManyToOne 建立持久化类之间的多对一关联关系
@ManyToMany 建立持久化类之间的多对多关联关系
(4)注解——配置命名查询
使用注解可以配置命名查询。配置命名查询的注解为@NamedQuery
@Entity
@Table(name = "EMP")
@NamedQuery(name = "selectEmp", query = "from Emp where empName like :ename")
public class Emp implements java.io.Serializable {
//缺省其他代码
}
总结:
Criteria查询是Hibernate提供的一种查询方式。
Criteria接口提供的分页查询方法和Query接口的相同,主要是setFirstResult()方法和setMaxResult()方法。
Criteria查询和HQL查询都支持连接查询,需要注意的是Criteria只支持内连接和迫切左外连接。
Hibernate提供了Hibernate Annotations扩展包,它可以替换复杂的hbm.xml文件,使得Hibernate程序开发大大简化。