`
一日一博
  • 浏览: 229569 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Hibernate4之Session一级缓存

阅读更多

Session缓存的作用:
1.减少访问数据库的频率,应用程序从内存中读取持久化对象的速度显然比到数据库查询数据的速度快多了,因此Session的缓存可以提高数据库的访问性能。
2.保证缓存中的对象与数据库中的记录保持同步,当缓存中持久化对象的状态发生了变化,Session并不会立即执行相关的SQL语句,这使得Session能够把几条相关的Sql语句合并为一条sql语句,以便减少访问数据库的次数,从而提高应用程序的性能。


Hibernate中的实体对象的三种状态:
1:瞬时(Transient) - 由new操作符创建,且尚未与Hibernate Session 关联的对象被认定为瞬时的。瞬时对象不会被持久化到数据库中,也不会被赋予持久化标识(identifier)。 如果瞬时对象在程序中没有被引用,它会被垃圾回收器销毁。 使用Hibernate Session可以将其变为持久状态,Hibernate会自动执行必要的SQL语句。

2:持久(Persistent) - 持久的实例在数据库中有对应的记录,并拥有一个持久化标识。 持久的实例可能是刚被保存的,或刚被加载的,无论哪一种,按定义,它存在于相关联的Session作用范围内。 Hibernate会检测到处于持久状态的对象的任何改动,在当前操作单元执行完毕时将对象数据与数据库同步。开发者不需要手动执行UPDATE。将对象从持久状态变成瞬时状态同样也不需要手动执行DELETE语句。

3:脱管(Detached) - 与持久对象关联的Session被关闭后,对象就变为脱管的。 对脱管对象的引用依然有效,对象可继续被修改。脱管对象如果重新关联到某个新的Session上, 会再次转变为持久的,在脱管期间的改动将被持久化到数据库。


通过Session接口来操作Hibernate
新增——save方法、persist方法
1:persist() 使一个临时实例持久化。然而,它不保证立即把标识符值分配给持久性实例,这会发生在flush的时候。persist() 也保证它在事务边界外调用时不会执行 INSERT 语句。这对于长期运行的带有扩展会话/持久化上下文的会话是很有用的。
2:save() 保证返回一个标识符。如果需要运行INSERT来获取标识符(如 "identity" 而非"sequence" 生成器),这个INSERT将立即执行,不管你是否在事务内部还是外部。这对于长期运行的带有扩展会话/持久化上下文的会话来说会出现问题。

当我们调用了session.save(UserModel)后:
1:TO--->PO:Hibernate先在缓存中查找,如果发现在内部缓存中已经存在相同id的PO,就认为这个数据已经保存了,抛出例外。
如果缓存中没有,Hibernate会把传入的这个TO对象放到session控制的实例池去,也就是把一个瞬时对象变成了一个持久化对象。
如果需要Hibernate生成主键值,Hibernate就会去生成id并设置到PO上
2:客户端提交事务或者刷新内存
3:根据model类型和cfg.xml中映射文件的注册来找到相应的hbm.xml文件
4:根据hbm.xml文件和model来动态的拼sql,如下:
insert into 表名(来自hbm.xml) (字段名列表(来自hbm.xml )) values(对应的值的列表(根据hbm.xml从传入的model中获取值))
5:真正用JDBC执行sql,把值添加到数据库
6:返回这个PO的id

修改——load方法、update方法、merge方法和saveOrUpdate方法
1:直接在Session打开的时候load对象,然后修改这个持久对象的属性,在事务提交的时候,Hibernate会判断是否有值改变了,如果没有改变则不会发出SQL,如果改变了会自动flush到数据库中,不过update语句会修改所有字段的值,不管有没有改变(虽然不影响结果,但是不推荐这种方式)。
2:update(会判断修改的对象在session中是否存在,如果不存在,会发出一条修改所有字段的update语句,如果存在,则会比对修改的值,发出修改值不同的update语句)
3:merge(会判断修改的对象在session中是否存在,如果不存在,会去数据库查出数据合并,如果有修改过的数据,发出修改值不同的update语句,如果没有修改就不会发出update语句)
4:自动状态检测:saveOrUpdate方法


update和merge做如下的事情:
1:如果数据库里面存在你要修改的记录,update每次是直接执行修改语句;而merge是先在缓存中查找,缓存中没有相应数据,就到数据库去查询,然后再合并数据,如果数据是一样的,那么merge方法不会去做修改,如果数据有不一样的地方,merge才真正修改数据库。
2:如果数据库中不存在你要修改的记录,update是报错;而merge方法是当作一条新增的值,向数据库中新增一条数据。
3:update后,传入的TO对象就是PO的了,而merge还是TO的。
4:如果你确定当前session没有包含与之具有相同持久化标识的持久实例,使用update()。如果想随时合并改动而不考虑session的状态,使用 merge()。换句话说,在一个新 session中通常第一个调用的是update()方法,以保证重新关联脱管对象的操作首先被执行。
5:请注意:使用update来把一个TO变成PO,那么不管是否修改了对象,都是要执行update sql语句的。

saveOrUpdate做如下的事情:
1:如果对象已经在本session中持久化了,不做任何事
2:如果另一个与本session关联的对象拥有相同的持久化标识,抛出一个异常
3:如果对象没有持久化标识属性,对其调用save()
4:如果对象的持久标识表明其是一个新实例化的对象,对其调用save()。
5:如果对象是附带版本信息的(通过 <version> 或 <timestamp>)并且版本属性的值表明其是一个新实例化的对象,save() 它。
6:否则update()这个对象

merge做如下的事情:
1:如果session中存在相同持久化标识的实例,用用户给出的对象的状态覆盖旧有的持久实例
2:如果session中没有相应的持久实例,则尝试从数据库中加载,或创建新的持久化实例
3:最后返回该持久实例
4:用户给出的这个对象没有被关联到session上,它依旧是脱管的

merge和saveOrUpdate方法区别:
merge方法是把我们提供的对象转变为托管状态的对象;而saveOrUpdate则是把我们提供的对象变成一个持久化对象;说的通俗一点就是:saveOrUpdate后的对象会纳入session的管理,对象的状态会跟数据库同步,再次查询该对象会直接从session中取,merge后的对象不会纳入session的管理,再次查询该对象还是会从数据库中取。

删除(Id的生成方式为assigned的情况)
当我们调用了session.delete(UserModel)后:
1:根据model的主键在数据库里面查找数据,来保证对象的存在,然后把找到的对象放到内存里面,如果此时在hibernate的实例池中已经存在对应的实体对象(注意:代理对象不算实体对象),就抛出例外。
2:如果此时在hibernate的实例池中不存在对应的实体对象,那么就把对象放到内存里面,但会标识成待删除的对象,就不可以被load等使用了。
3:如果对象还是不存在,那么就直接返回了(注意,这个时候是不抛出例外的)。也就是说,delete之前会执行一个查询语句。
4:客户端提交事务或者刷新内存
5:判断待删除的PO是否存在,存在才需要删除,否则不需要删除
6:如果要删除,才执行以下的步骤。先根据model类型和cfg.xml中映射文件的注册来找到相应的hbm.xml文件
7:根据hbm.xml文件和model来动态的拼sql,如下:
delete from 表名(来自hbm.xml) where 主键=值(来自model)
8:真正用JDBC执行sql,把数据从数据库中删除

删除(Id的生成方式为非assigned的情况)
当我们调用了session.delete(UserModel)后:
1:根据model的主键在hibernate的实例池中查找对应的实体对象(注意:代理对象不算实体对象),找到就使用该对象。
2:如果内存中没有对应的实体对象,就到数据库中查找来保证对象的存在,把找到的对象放到内存里面,而且不会标识成待删除的对象,可以继续被load等使用。代理对象也需要去数据库中查找数据。
3:如果对象还是不存在,那么就抛出例外。也就是说,delete之前可能会执行一个查询语句。
4:客户端提交事务或者刷新内存
5:根据model类型和cfg.xml中映射文件的注册来找到相应的hbm.xml文件
6:根据hbm.xml文件和model来动态的拼sql,如下:
delete from 表名(来自hbm.xml) where 主键=值(来自model)
7:真正用JDBC执行sql,把数据从数据库中删除

值得注意的是,Session只有在清理缓存的时候的才执行delete语句。 commit会调用session的flush方法,刷出session中的数据到数据库,说白了就是同步session中数据到数据库并提交事务。
此外,只有当调用Session的close()方法时,才会从Session的缓存中删除该对象。——————PO(持久化对象)---->DO(托管对象)


查询load和get方法
当我们调用了s.load(UserModel.class, “主键值");后:
1:根据model类型和主键值在一级缓存中查找对象,找到就返回该对象
2:如果没有找到,判断是否lazy=true,如果是,那就生成一个代理对象并返回;否则就先查找二级缓存,二级缓存没有,就查找数据库。如果是返回代理对象的(这时候还不会发出SQL语句),在第一次访问非主键属性的时候(这时候就会发出SQL语句),先查找二级缓存,二级缓存中没有才真正查找数据库,如果还没有找到就抛出异常。
3:如果需要查找数据库的话,会根据model类型和cfg.xml中映射文件的注册来找到相应的hbm.xml文件
4:根据hbm.xml文件和model来动态的拼sql,如下:
select 字段列表(来自hbm.xml) from 表名(来自hbm.xml) where 主键=值
5:真正用JDBC执行sql,把数据从数据库中查询出来到rs里面。如果找不到就报错
6:从结果集---〉Model,然后返回model

注意:load方法开不开事务都可以执行查询语句。

当我们调用了s.get(UserModel.class, “主键值");后:
1:先根据model类型和主键值查找缓存,如果存在具体的实体对象,就返回;如果存在实体的代理对象(比如前面load这条数据,但是还没有使用,那么load生成的是一个只有主键值的代理对象),那么查找数据库,把具体的数据填充到这个代理对象里面,然后返回这个代理对象,当然这个代理对象此时已经完全装载好数据了,跟实体对象没有什么区别了。
2:如果要查找数据库,先根据model类型和cfg.xml中映射文件的注册来找到相应的hbm.xml文件
3:根据hbm.xml文件和model来动态的拼sql,如下:
select 字段列表(来自hbm.xml) from 表名(来自hbm.xml) where 主键=值
4:真正用JDBC执行sql,把数据从数据库中查询出来到rs里面,没有值就返回null
5:从结果集---〉Model,然后返回model

注意:get方法开不开事务都可以执行查询语句。

Session清理缓存的时间点:
清理缓存:是指按照缓存当中的对象的状态的变化来同步更新数据库。
1.当程序调用事物提交的时候,tx.commit()方法被执行时,当前session对象会调用close方法,然后再向数据库提交事物。
2.当程序显示调用session的flush()方法的时候,也会清理缓存。

每间隔一段时间,Session会执行一些必需的SQL语句来把内存中的对象的状态同步到JDBC连接中。这个过程被称为刷出(flush),默认会在下面的时间点执行:
在某些查询执行之前
在调用org.hibernate.Transaction.commit()的时候
在调用Session.flush()的时候
涉及的SQL语句会按照下面的顺序发出执行:
所有对实体进行插入的语句,其顺序按照对象执行Session.save()的时间顺序
所有对实体进行更新的语句
所有进行集合删除的语句
所有对集合元素进行删除,更新或者插入的语句
所有进行集合插入的语句
所有对实体进行删除的语句,其顺序按照对象执行Session.delete()的时间顺序
(有一个例外是,如果对象使用native方式来生成ID(持久化标识)的话,它们一执行save就会被插入。)

除非你明确地发出了flush()指令,关于Session何时会执行这些JDBC调用是完全无法保证的,只能保证它们执行的前后顺序。 当然,Hibernate保证,Query.list(..)绝对不会返回已经失效的数据,也不会返回错误数据。




  • 大小: 8.9 KB
分享到:
评论

相关推荐

    hibernate一级和二级缓存配置与详解

    一级缓存是Hibernate默认提供的缓存,它是Session级别的,每个Hibernate Session都有一个私有的、本地的一级缓存。当我们在Session中对对象进行 CRUD(创建、读取、更新、删除)操作时,这些对象会被自动放入一级...

    hibernate一级缓存和二级缓存的区别与联系

    它是一个事务范围的缓存,也就是说,每个 Hibernate Session 对应一个一级缓存,仅在当前事务中有效。一级缓存主要存储了 Session 在当前事务中加载和修改的对象实例。当 Session 执行 CRUD 操作时,对象会自动放入...

    hibernate一级缓存、二级缓存和查询缓存

    一级缓存是Hibernate内置的Session级别的缓存,也被称为事务性缓存。每当我们在Session中进行对象的CRUD(创建、读取、更新、删除)操作时,这些操作实际上并未立即同步到数据库,而是被暂时保存在一级缓存中。一级...

    Hibernate一级缓存和二级缓存

    一级缓存是每个Hibernate Session内的缓存,它是一个内存中的对象图,存储了最近查询到的持久化对象。当我们在Session中执行CRUD(创建、读取、更新、删除)操作时,这些对象会被自动放入一级缓存。一级缓存的主要...

    hibernate一级缓存

    一级缓存,也称为session缓存,是每个Hibernate Session内部管理的一个内存结构。在本篇文章中,我们将深入探讨一级缓存的工作原理、作用以及如何有效地利用它。 ### 一级缓存的工作机制 1. **对象持久化过程**:...

    Hibernate性能优化:一级缓存

    1. 当我们通过Session加载或保存一个实体对象时,Hibernate会将其放入一级缓存。 2. 同一次会话中,再次尝试加载该对象时,Hibernate会首先检查一级缓存,如果找到就直接返回,避免了数据库查询。 3. 一级缓存是本地...

    hibernate的一级缓存和二级缓存

    一级缓存,也称为Session缓存,是每个Hibernate Session实例私有的。当Session执行查询操作时,会将结果存储在一级缓存中。如果同一Session再次执行相同的查询,Hibernate将直接从一级缓存获取数据,避免了重复的...

    Hibernate一级缓存、二级缓存以及查询缓存实例

    一级缓存是Hibernate默认提供的缓存,它是每个Session级别的,也被称为事务级缓存。当我们在Session中进行对象的增删改查操作时,这些对象会被放入一级缓存中。一级缓存的作用在于避免频繁地与数据库交互,提高效率...

    Hibernat一级缓存(源码)

    4. 一级缓存的生命周期与 Session 对象相同,当 Session 被关闭时,一级缓存中的数据也会被清除。 源码分析: Hibernate 的一级缓存主要由 `org.hibernate.engine.spi.SessionImplementor` 接口和它的实现类 `org....

    day37 05-HIbernate二级缓存:一级缓存更新同步到二级缓存及二级缓存配置文件

    本篇文章将深入探讨Hibernate的二级缓存机制,以及如何进行一级缓存与二级缓存的同步,同时还会介绍二级缓存的配置文件设置。 一级缓存是Hibernate默认提供的缓存,每个SessionFactory实例都有一个一级缓存。当对象...

    springboot+jpa(hibernate配置redis为二级缓存) springboot2.1.4

    通常,一级缓存由Hibernate Session管理,而二级缓存则可以跨越多个Session进行共享。 在Spring Boot项目中配置Redis作为Hibernate的二级缓存,我们需要以下步骤: 1. **添加依赖**: 首先,在`pom.xml`文件中...

    Hibernate4二级缓存实例(源码)

    1. **Hibernate二级缓存**:二级缓存是Hibernate在一级缓存(Session级别的缓存)之外提供的全局共享缓存,可以跨Session共享数据。它允许多个并发用户访问相同的数据,减少对数据库的访问次数,提高系统性能。 2. ...

    Hibernate缓存策略(一级缓存、二级缓存).docx

    一级缓存,也称为Session缓存,是Hibernate内置的默认缓存。它是一个事务级别的缓存,每个持久化类的实例都有唯一的OID(Object Identifier)。当我们在同一个Session内多次读取同一对象时,Hibernate会首先检查一级...

    Hibernate二级缓存

    Hibernate二级缓存是一种提高应用程序性能的技术,它将数据存储在SessionFactory级别的缓存中,使得数据可以在不同的Session之间共享。这与一级缓存(Session级别)不同,一级缓存仅存在于单个Session生命周期内,当...

    hibernate开启二级缓存和查询缓存

    一级缓存是 Hibernate 内置的 Session 缓存,它是每个 Hibernate Session 的私有缓存。当对象被加载到 Session 中时,它们会被自动缓存。在同一个 Session 内部,对相同数据库记录的操作会直接在缓存中进行,无需...

    Spring集成的Hibernate配置二级缓存

    在Hibernate中,一级缓存是每个Session内部的缓存,它自动管理实体的状态,当一个实体被加载到Session后,该实体的状态就会被缓存。然而,一级缓存的范围仅限于单个Session,当Session关闭后,其中的数据就会丢失。...

    Hibernate-nosession

    然而,需要注意的是,Hibernate-nosession模式虽然在某些场景下提高了效率,但同时也失去了Hibernate的一些优势,如对象缓存、事务管理和懒加载等。因此,我们在选择使用nosession模式时,需要根据具体的应用需求和...

    Spring4+Hibernate4二级缓存实例源码

    在Hibernate中,一级缓存是每个Session级别的,它存储了当前Session中所有持久化对象的副本,当Session关闭时,一级缓存中的数据会被清除。而二级缓存是SessionFactory级别的,它可以跨Session共享,即使Session关闭...

    hibernate二级缓存实例

    一级缓存是Session级别的,每个Session都有自己的一级缓存,用于存储当前Session操作的对象。而二级缓存则是SessionFactory级别的,它跨越了多个Session,是全局共享的,可以被多个并发的Session共同使用。 二级...

Global site tag (gtag.js) - Google Analytics