Hibernate学习

1.什么是Hibernate

Hibernate是一个开放源代码的ORM创建,对JDBC进行了轻量级的对象封装,使Java开发人员可以使用面向对象的编程思想来操作数据库

2.什么是ORM

Object Relation Mapping对象关系映射:随着面向对象的软件开发方法发展而产生的。用来把对象模型表示对象映射到基于SQL的关系模型数据库结构中去。简单地说就是将程序中的实体和数据库表建立对应关系

3.Hibernate SessionFactory

SessionFactory是工厂类,是生成Session对象的工厂类

(1)SessionFactory类的特点

  • 由Configuration通过加载配置文件创建该对象
  • SessionFactory对象中保存了当前的数据库配置信息和所有映射关系以及预定义的SQL语句。同时SessionFactory还负责维护Hiberante的二级缓存
  • 预定义SQL语句
  • 一个SessionFactory实例对应一个数据库,应用从该对象中获得Session实例
  • SessionFactory是重量级的,意味着不能随意创建或销毁它的实例。如果只访问一个数据库,只需要创建一个SessionFactory实例,且在使用初始化的时候完成
  • SessionFactory需要一个较大的缓存,用来存放预定义的SQL语句及实体的映射信息,另外可以配置一个缓存插件,这个插件被称为Hibernate的二级缓存,被多线程所共享

(2)使用SessionFactory注意事项

一般应用使用一个SessionFactory,最好是在应用启动时就完成初始化

4.Hibernate Session

(1)Session概述

  • Session是在Hibernate中使用最频繁的接口,也被称为持久化管理器。提供了和持久化有关的操作,如增删改查和加载
  • Session是应用程序与数据库之间交互操作的一个单线程对象,是Hiberante运作的中心
  • 所有持久化对象必须在session的管理下才可以进行持久化操作
  • Session对象有一个一级缓存,显示执行flush之前,所有的持久化操作的数据都缓存在session对象处
  • 持久化类与Session关联起来后就具有了持久化的能力

(2)Session的特点

  • 非线程安全,应避免多个线程使用同一个Session实例
  • Session是轻量级的,创建和销毁不会消耗太多的资源,应为每次客户请求分配独立的Session实例
  • Session有一个缓存,称为Hibernate的一级缓存,每个Session实例都有自己的缓存

5.Hibernate Transaction

Transaction特点:

  • Hibernate框架默认情况下事务不自动提交,需要手动提交事务
  • 如果没有开启事务,则每个Session的操作,相当于一个独立的事务

6.Hibernate主键生成策略

Hibernate提供的主键生成策略,使我们可以在实体类的映射xml文件中设定关键字来告诉Hibernate我们要使用的主键生成方式,然后Hibernate会根据设定完成数据库的主键控制

  • UUID,increment,Hilo,assigned:对数据库无依赖
  • identity:依赖Mysql或sql server,主键值不由Hibernate维护
  • sequence:适合于oracle等支持序列的dbms,主键值不由Hibernate维护,由序列产生
  • native:根据底层数据库的具体特性选择适合的主键生成策略,如果是mysql或sql server,选择identity,如果是Oracle,选择sequence

一般来说推荐UUID,因为生成主键唯一,且对数据库无依赖,可移植性强

7.Hibernate get和load查询

在Hibernate中,如果要从数据库中得到一个对象,通常有两种方式,一种是通过session.get()方法,另一种是session.load()方法

(1)load加载方式

当用load方法来得到一个对象时,Hibernate会使用延迟加载的机制来加载这个对象,即:当我们使用session.load()方法来加载一个对象时,此时并不会发出SQL语句,此前得到的这个对象其实是一个代理对象,这个代理对象只保存了实体对象的id值,只有当我们要使用这个对象得到其他属性时,这个时候才会发出SQL语句,从数据库中去查询我们的对象

(2)get加载方式

当用session.get()方法来得到一个对象时,无论我们是否使用这个对象,都会发出SQL语句从数据库中查询出来

对比:使用load的加载方法比get的加载方式性能要好一些,因为load加载时,得到的只是一个代理对象,当真正需要的该对象时再去数据库中查询

(3)使用get和load时的问题

  • 若使用get方式来加载对象,当我们试图得到一个id不存在的对象时,会报空指针异常
  • 若使用load方式来加载对象,当我们试图得到一个id不存在的对象时,会报ObjectNotFoundException异常

8.Hibernate对象状态

(1)Hibernate的持久化类的状态

  • 瞬时态:Transient Object
    没有持久化标识OID,没有被纳入到Session对象的管理
  • 持久态:Persistent Object
    有持久化标识OID,已经被纳入到Session对象的管理
  • 托管态(离线态):Detached Object
    有持久化标识OID,没有被纳入到Session对象的管理

9.Hibernate一级缓存和快照

Hibernate的一级缓存是指Session缓存,通过查看Session接口的实现类源码发现有两个类:

  • actionQueue:行动队列,主要记录crud操作的相关信息
  • persistenceContext:持久化上下文,真正的缓存

在Session中定义了一系列的集合来存储数据,它们构成了Session的缓存,只要Session没有关闭,它就会一直存在。当我们通过Hibernate中的Session提供的一些API例如save()、get()、update()等进行操作时,就会将持久化对象保存到Session中,当下一次再去查询缓存中具有的对象(通过OID值来判断),就不会去从数据库中查询了,而是直接从缓存中获取。

Hibernate的一级缓存存在的目的就是为了减少对数据库的访问

快照:当前一级缓存里面对象的散装数据(对象的属性和行为)

一级缓存其底层使用了一个Map集合来存储,Map的key存储的是以及缓存对象,value存储的是快照

一级缓存的特点:

  • 当我们通过session的save、update、saveOrUpdate方法进行操作时,如果一级缓存中没有对象,则会从数据库中中查询到这些对象,并存储到一级缓存中
  • 当我们通过session的load、get、Query的list等方法进行操作时,会先判断一级缓存中是否存在数据,如果没有才会从数据库中获取,并且将查询的数据存储到一级缓存中
  • 当使用session的close方法时,session缓存将清空

一级缓存常用的API:

  • clear():清空一级缓存
  • evict():清空一级缓存中指定的某个对象
  • refresh(): 重新查询数据库,用数据库中的信息来更新一级缓存与快照区

10.Hibernate lazy延迟加载

(1)延迟加载的概念

当Hibernate从数据库中加载某个对象时,不加载关联的对象,而是生成了代理对象,获取使用session中的load的方法时,获取到的也是代理对象

(2)立即加载

当Hibernate从数据库中加载某个对象时,加载关联的对象,生成的实际对象,获取使用session中的get方法和获取到的是实际对象

(3)为什么要使用延迟加载

延迟加载策略可以避免加载应用程序不需要访问的关联对象,以提高应用程序的性能

(4)立即加载的缺点

Hibernate在查询某个对象时,立即查询与之关联的对象,这种策略存在两大不足:

  • select的语句数目太多,需要频繁的访问数据库,会影响查询的性能
  • 加载与访问对象关联的对象完全是多余的操作,这些多余的操作会占内存,造成内存空间的浪费

(5)什么时候使用延迟加载?什么时候使用立即加载?

如果程序加载一个持久化对象的目的是访问它的属性,则可以采用立即加载;如果程序加载一个持久化对象的目的是仅仅为了获得它的引用,则可以采用延迟加载

11.Hibernate fetch抓取策略

抓取策略指的是使用Hibernate查询一个对象时,查询其关联对象应该如何查询

(1)连接抓取:Hibernate通过SELECT语句使用OUTER JOIN来获得对象的关联实例或者关联集合

(2)查询抓取:另外发送一条SELECT语句抓取当前对象的关联实体或集合

(3)子查询抓取:另外发送一条SELECT语句抓取在前面查询到的所有实体对象的关联集合

(4)批量抓取:对查询抓取的优化方案,通过指定一个主键或外键列表,Hibernate使用单条SELECT语句获取一批对象实例或集合

12.Hibernate二级缓存

SessionFactory缓存可以依据功能和目的的不同而划分为内置缓存和外置缓存

SessionFactory的内置缓存中存放了映射元数据和预定义SQL语句,映射元数据是映射文件中数据的副本,而预定义SQL语句是在Hibernate初始化阶段根据映射元数据推导出来的。SessionFactory的内置缓存是只读的,应用程序不能修改缓存中的映射元数据和预定义SQL语句,因此SessionFactory不需要进行内存缓存与映射文件的同步

SessionFactory的外置缓存是一个可配置的插件。在默认情况下,SessionFactory不会启动这个插件。外置缓存的数据是数据库数据的副本,外置缓存的介质可以是内存或者磁盘。SessionFactory的外置缓存也称为Hibernate的二级缓存

由于Hibernate的二级缓存是作用在SessionFactory范围内的,因此比一级缓存的范围更广,可以被所有的Session对象所共享

二级缓存的工作内容:
同一级缓存一样,也是针对对象ID来进行缓存。因此,二级缓存的作用范围是针对根据ID获得对象的查询

  • 在执行各种条件查询时,如果所获得的结果集为实体对象的集合,则会把所有的数据对象根据ID放入到二级缓存中
  • 当Hibernate根据ID访问数据对象时,首先会从Session一级缓存中查找,如果查不到并且配置了二级缓存,则会从二级缓存中查找。若还找不到,就会查询数据库,将结果按照ID放入到缓存中
  • 删除、更新、增加数据时同时更新缓存

二级缓存的使用范围:
HIbernate的二级缓存作为一个可插入的组件在使用的时候可以进行配置的,但并不是所有的对象都适合放在二级缓存中

通常被放入二级缓存中的数据如下:

  • 很少被修改的数据
  • 不是很重要的数据,允许出现偶尔并发的数据
  • 不会被并发访问的数据
  • 参考数据

不适合于放在二级缓存中的数据:

  • 经常被修改的数据
  • 财务数据,绝对不允许出现并发
  • 与其他应用共享的数据

二级缓存的策略:
当多个并发的事务同时访问持久化层的缓存中的相同的数据时,回引发并发问题,必须采用重要的事务隔离措施

  • 只读缓存:程序只需要读取一个持久化的实例,但是不打算修改
  • 读/写缓存:程序需要更新数据,若需要序列化事务隔离级别,则不能使用这种缓存策略

对于经常被读取但是很少修改的数据,可以采用这种隔离类型,可以防止脏读这类并发问题

  • 不严格的读/写缓存:程序偶尔需要更新数据,也不需要十分严格的事务隔离

对于极少被修改,并允许偶尔脏读的数据,可以采用这种并发访问策略

  • 事务缓存:经常被读取但很少修改的数据

事务性并发访问策略的隔离级别最高,依次时读/写型和不严格读/写型,只读型的隔离级别最低。事务的隔离级别越高,并发性能就越低

13.Hibernate事务管理

事务就是逻辑上的一组操作,组成这组操作的各个单元要么全部成功,要么全部失败

事务4个特性:

  • 原子性:强调事务时不可分割的最小单元
  • 一致性:事务在执行前后,要保证数据的一致
  • 隔离性:一个事务在执行的过程中,不应该受到其他事务的干扰
  • 持久性:事务一旦结束,数据持久化到数据库

若不考虑事务的隔离性,则可能会丢失更新
(1)产生丢失更新的原因

两个不同的事务在某一个时刻对同一数据进行读取后,先后进行修改,导致第一次操作数据丢失

(2)解决方式

使用数据库锁机制防止数据丢失

  • 共享锁:允许并发事务读取一个资源。资源上存在共享锁时,任何其他事务都不能修改数据。一旦已经读取数据,便立即释放资源上的共享锁,除非将事务隔离级别设置为可重复读或更高级别,或者在事务生存周期内用锁定提示保留共享锁
  • 排它锁:可以防止并发事务对资源进行访问。其他事务不能读物或修改排它锁的数据

脏读:一个事务读取到另一个事务的为提交数据

不可重复读:一个事务读取到另一个事务提交的数据,会导致两次读取的结果不一致

幻读:一个事务读取到领域给事务提交的数据会导致两次读取结果不一致

我们可以通过设置隔离级别来解决读的问题.

READ_UNCOMMITED 读取未提交:它引发所有的隔离问题

READ_COMMITTED 读已提交:阻止脏读,可能发生不可重复读与虚读.

REPEATABLE_READ 重复读::阻止脏读,不可重复读:可能发生虚读

SERIALIZABLE 串行化:解决所有问题 不允许两个事务,同时操作一个目标数据。(效率低下,但操作安全是最安全的)

Hibernate中设置事务隔离级别:
1代表的事务隔离级别为  READ UNCOMMITTED
2代表的事务隔离级别为  READ COMMITTED
4.代表的事务隔离级别为  REPEATABLE READ
8代表的事务隔离级别为   SERIALIZABLE

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值