Hibernate学习——(四)Session及生命周期中的三种状态

Session接口是Hibernate向应用程序提供的操纵数据库的最主要的接口,它提供了基本的保存,更新,删除和加载(不是“查询”!)Java对象的方法。

Session具有一个缓存,位于缓存中的对象称为持久化对象,它和数据库中的相关记录对应。Session能够在某些时间点按照缓

存中对象的变化来执行相关的SQL语句,来同步更新数据库。站在持久化的角度,Hibernate把对象分为3种状态:Transient、

Persistent、Detached。Session的特定方法能使对象从一个状态到另一个状态。

在Session集合的实现中包含了一系列的Java集合,这些Java集合构成了Session缓存,只要Session实例没有结束生命周期,

且没有清理缓存,则放在缓存中的对象也不会结束生命周期。利用Hibernate的这个一级缓存,能够减少Hibernate应用程序访问数据

库的频率。

操作Session缓存有以下几个方法:

flush():使数据表中的记录和Session缓存中的对象的状态保持一致,为了保持一致,则可能会发送对应的SQL语句

1、在Transaction的commit()方法中,先调用Session的flush()方法,再提交事务。

2、flush()方法可能会发送SQL语句,但不会提交事务。

refresh():会强制发送SELECT语句,以使Session缓存中对象的状态和数据表中对应的记录保持一致。在这种方法的使用中会遇到

事务隔离方面的问题,在之后再详细介绍。

clear():清理缓存。缓存中的内容被清空。


前面说到了站在持久化的角度,Hibernate把对象分为3种状态:Transient、Persistent、Detached。Session的特定方法能使对

象从一个状态到另一个状态。


三种状态的主要区别是:a>有没有Id   b>Id在数据库中有没有   c>Id在session缓存里有没有.

Transient:刚new出来的一个对象,session缓存和数据库中都没有;

Persistent:session缓存和数据库中都存在,有Id;

Detached:session已经结束,故session缓存中不存在,而数据库中存在。

//********************************************************************介绍方法*************************************************************

save():将临时对象转变为持久化对象,会为对象分配Id,在save方法之前设置Id是无效的(如果设置了Id生成策略),持久化对象

的Id是不能修改的。


persist():功能和save相同,但是并不保证标识符被立刻填入到持久化实例中,标识符的填入可能被推迟到flush()的时候。但是它

证当它在一个事务外部被调用时,不立刻触发一个insert事件,而save方法会立刻返回一个insert事件不管是不是在事务内部还是外

部。


get():会立即加载对象,即是立即检索。


load():同样可以加载对象,但是是延迟加载,如果不使用该对象,则不会立即执行查询操作,而是返回一个中间代理对象。如果数

据表中没有数据get方法会返回null,而load方法会抛出异常(但是如果不使用这个对象,仅仅是load了,不会报异常)。由于load的

延迟加载特性,如果在真正使用到这个对象之前就将session关掉的话,就会抛出一个LazyInitializationException。


update():可以更新transient和detached对象, 将其变为persistent状态,同时将其内容更新(发送update语句)。单纯更新一个

transient对象的非主键属性会返回一个错误(因为执行update语句需要知道其id才可以执行),但是如果对于这个transient对象

直接set一个主键的话,可以执行更新,且需要显式调用update语句。如果是更新detached状态下的值,可以直接把对象load出来之后

用set方法,而且不需要显式调用update方法,因为在一个事务commit的时候,会自行执行flush()方法(如果此时其实并无实际更新,则不会执行

update语句)。

以上update方法在一次update过程中都会遍历一遍所有的字段,如果一个字段的内容很多的话,会严重影响效率,因此有以下

几个解决方案:

①xml中设定property标签的update属性或者在@Column中设置updatable属性为false(使用少,因为十分不灵活)

②xml中设定class的dynamic-update属性为false。但是此方法在annotation声明中用不了。

③使用merge()方法(但是实际上额外增加了一条select语句,更不划算)

④使用HQL语句(推荐)


delete():执行删除操作,只要主键对应,则会在事务提交或者是flush缓存的时候提交一条delete语句。如果没有对应主键,则该方

法会抛出一个异常。(只要有主键就可以执行删除操作)


saveOrUpdate:对于一个transient对象,相当于是save方法,会执行一条insert语句;对于persistent或者detached对象,相当于是

update方法,会执行一条update语句。


clear():清楚session缓存。


flush():强制将缓存中内容和数据库内容做同步





ps:事务相关知识记录:

“事务”的特性:“A.C.I.D.” ===>Atomicity、Consistency、Isolation、Durability(原子性、一致性、隔离性、持续性)

对于同时运行的多个事务,当这些访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题:

脏读:又称无效数据的读出,是指在数据库访问中,事务T1将某一值修改,然后事务T2读取该值,此后T1因为某种原因撤销对该值

的修改,这就导致了T2所读取到的数据是无效的。

不可重复读:是指在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。这是由于查询时系统中其他事务修改的提

交而引起的。比如事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了

不同的结果。

幻读:是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的“全

部数据行”。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,以后就会发生操作第一个

事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。

事务隔离级别:

READ_UNCOMMITTED(1):允许脏读取,但不允许更新丢失。如果一个事务已经开始写数据,则另外一个事务则不允许同时进

行写操作,但允许其他事务读此行数据。

READ_COMMITTED(2):允许不可重复读取,但不允许脏读取。读取数据的事务允许其他事务继续访问该行数据,但是未提交

的写事务将会禁止其他事务访问该行。

REPETABLE_READ(4):禁止不可重复读取和脏读取,但是不能完全避免出现幻读数据。读取数据的事务将会禁止写事务(但允

许读事务),写事务则禁止任何其他事务。

SERIALIZEABLE(8):提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,不能并发执行。

JDBC数据库连接使用数据库默认的隔离级别,在Hibernate的配置文件中可以显式的设置其隔离级别,每一个隔离级别对应一

个整数(如上述四个英文名旁边括号里的数字)。设置方法为在Hibernate.cfg.xml中加入:

<property name="connection.isolation">[隔离等级编号]</property>



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值