hibernate5(6)操纵对象入门[1]Session缓存

java对象在JVM中的存活条件

在java中,我们使用User user = new User();来创建一个java对象时,JVM会为其分配一块内存空间,此时,这个对象被变量“user”引用,那么它就会一直存在于内存中,而如果我们我们的“引用者user”升级了,User user = new VipUser()。那么原来new User()不再被任何变量引用,它就会结束自己的生命周期,然后会被JVM的智能垃圾回收期回收处理,以免再占用内存。
从以上分析,我们知道了java对象存活的条件就是:被(至少一个)变量引用

hibernate的对象存活条件

同样的,假设在我们使用hibernate访问数据库获取了一个小A对象,这个小A一样有它的存活条件,但与一般java对象不同,即使我们没有创建任何变量来引用小A,我们的小A还是能够活得好好的,这是因为小A被hibernate的Session缓存下来了。

理解Session的缓存机制

1. 缓存的实现机制:

在Session接口的实现类中,我们定义了一系列的java集合来存放从数据库中获取的数据,只要我们的Session实例没有结束声明周期,那么存放其中的对象就不会结束其生命周期。

2. Session缓存的作用

1. 减少对数据库的访问次数,优化性能。

比如我们来看下面的例子

Long time1 = System.currentTimeMillis();//记录时间
User user1_1 = session.get(User.class,1);
Long time2 = System.currentTimeMillis();//记录结束时间1
System.out.println("user1_1获取完毕,耗时:"+(time2 - time1)+"毫秒,准备开始获取user1_2");
User user1_2 = session.get(User.class,1);//与上面id相同
System.out.println("user1_2获取完毕,耗时:"+(System.currentTimeMillis() - time2 )+"毫秒,准备开始获取user2");
User user2 = session.get(User.class,2);
System.out.println(user1_1 == user1_2);
System.out.println(user1_2== user2);

运行程序,观察我们的打印信息:

Hibernate: select user0_.id as id1_0_0_, user0_.name as name2_0_0_ from t_user2 user0_ where user0_.id=?
user1_1获取完毕,耗时:26毫秒,准备开始获取user1_2
user1_2获取完毕,耗时:0毫秒,准备开始获取user2
Hibernate: select user0_.id as id1_0_0_, user0_.name as name2_0_0_ from t_user2 user0_ where user0_.id=?
true
false
在我们获取user1_2时,并没有查询数据库而且获取时间几乎为0,说明是直接从缓存中读取的,而在比较对象属性中,user1_1和user1_2相等,说明它们的引用地址也相同,而且必定与session缓存中的引用地址一致
从上面我们还能看到,Session标识缓存的不同对象,是通过对象类型和对象标识符id共同判别的,一旦两者一致,session即判别为同一对象,同时,我们也可归纳出利用session查询数据库的过程:比如我们要查询id为1的User,则查询过程如下时序图所示:

Created with Raphaël 2.1.0SessionSessionSession缓存Session缓存数据库数据库:1. 查找缓存是否有对象类型为User且id为12. 找到并返回2. 没找到则查询数据库3. 返回数据结果并缓存4. 返回数据到引用变量

2. 保证数据库中的记录和缓存中的相应对象内容一致

在session清理缓存(flush)时,会进行脏检查,如果发现缓存中的最新数据与数据库记录不一致,会将最新数据更新到数据库中。
那么,session是如何进行脏检查的呢?难道每次清理前,针对所有的缓存数据访问数据库来进行匹对?这样效率太低了。实际上,在上述时序图的第3步到第4步之间,Session会将获得的数据结果先copy一份(这份copy还未经任何处理,肯定是和数据库记录一致的),再返回给引用变量。这样我们将所有最新的数据与最初copy的校对一下,一旦出现差异,就将最新数据更新到数据库。

3. Session缓存的清理

在我们每次针对引用变量修改对象属性后,对应的Session缓存中的数据也会被修改,这是显然的,因为它们的所指向的内存地址是一致的。但修改后,hibernate并不会马上执行相应的数据库操作,只有在特定条件下,如session被清理特定的方法被调用才会访问数据库。这里谈谈session被清理的三个时间点:
1. 在完成事务提交之前,session会被清理一次。这样的好处是一方面可以减少在事务作用过程中,大量执行的数据库记录修改操作。另一方面还可以尽可能缩短当前事务对相关资源的锁定时间
2. 在执行一些复杂的查询操作时,需要清理缓存,更新数据库,确保查询得到的数据是最新的。
3. 显示地调用Session.flush()方法

如果我们不希望在上述的某些时刻清理,我们可以通过Session的setFlushMode()方法来定制,它提供了3种模式共我们选择:

模式 复杂查询方法被执行 事务提交时 显式调用flush() 使用场景
FlushMode.AUTO(默认模式) 清理 清理 清理 正常应用场景
FlushMode.COMMIT 不清理 清理 清理 需要避免过多查询操作清理缓存以提高性能的场景
FlushMode.NEVER 不清理 不清理 清理 需要长时间运行的复杂事务场景

tips:从上面我们还能看出,我们要修改用户信息,完全用显式地执行session.update(user)语句,只需直接修改Session缓存对象属性即可,如下所示

user.setName("newName");
session.flush();

我们数据库中相应的User记录name属性也被修改了!

此外,Session在清理缓存时,按照以下顺序执行sql语句。
1。按照应用程序调用save()方法的先后顺序,执行所有的对实体进行插入的insert语句。
2。所有对实体进行更新的update语句。
3。所有对实体进行删除的delete语句。
4。所有对集合元素进行删除、更新或插入的sql语句。
5。执行所有对集合进行插入的insert语句。
6。按照应用程序调用delete()方法的先后执行,执行所有对实体进行删除的delete语句。

时间: 2024-12-31 16:18:31

hibernate5(6)操纵对象入门[1]Session缓存的相关文章

hibernate5(8)操纵对象入门[3]操控对象封装方法

为什么要说是"封装方法"呢?因为它帮我们封装好了底层的增删改查操作,直接调用相应方法即可灵活地操作我们数据库数据.它们由Session接口提供,下面我们通过实例一一分析这些方法. 1.save方法 Session 的 save() 方法使一个临时对象转变为持久化对象 Session 的 save() 方法完成以下操作: 1. 把 User对象加入到 Session 缓存中,使它进入持久化状态 2. 选用映射文件指定的标识符生成器,为持久化对象分配唯一的 OID.在 使用代理主键的情况下

hibernate5(7)操纵对象入门[2]四大对象状态分析

状态类型 在hibernate中,java对象的声明周期对应有4种状态: 状态 说明 瞬时(Transient) 由new操作符创建,且尚未与Hibernate Session 关联的对象被认定为瞬时(Transient)的.瞬时(Transient)对象不会(在清理Session时)被持久化到数据库中,也不会被赋予持久化标识(identifier).使用Hibernate Session可以将其变为持久(Persistent)状态.(Hibernate会自动执行必要的SQL语句) 持久(Per

jsp内置对象入门(5) session对象详解

在学习完了request和response之后,我们来一起学习session对象,可以说,session对象和request对象是九大对象里最为重要的两个对象. session对象简介 在前面讲解session属性范围的时候,已经学习了关于session的一些用法,但是在实际的开发中,session的最为主要的用处是完成用户的登录.注销等常见的功能的,每一个session对象都表示不同的访问用户. session是javax.servlet.http.HttpSession接口的实例化对象,所有

ASP基础入门第八篇(ASP内建对象Application和Session)_应用技巧

 在上一篇中作者给大家详细介绍了 ASP 内建对象 Response 的使用方法,在这一篇中作者将继续给大家介绍另两个非常实用且重要的 ASP 的内建对象 Application 和 Session. 在 ASP 的内建对象中除了用于发送.接收和处理数据的对象外,还有一些非常实用的代表 Active Server 应用程序和单个用户信息的对象. 让我们先来看看 Application 对象.在同一虚拟目录及其子目录下的所有 .asp 文件构成了 ASP 应用程序.我们非但可以使用 Applica

第九篇 ASP内建对象Application和Session

在上一篇中作者给大家详细介绍了 ASP 内建对象 Response 的使用方法,在这一篇中作者将继续给大家介绍另两个非常实用且重要的 ASP 的内建对象 Application 和 Session. 在 ASP 的内建对象中除了用于发送.接收和处理数据的对象外,还有一些非常实用的代表 Active Server 应用程序和单个用户信息的对象. 让我们先来看看 Application 对象.在同一虚拟目录及其子目录下的所有 .asp 文件构成了 ASP 应用程序.我们非但可以使用 Applicat

第九课:ASP内建对象Application 和 Session

在上一篇中作者给大家详细介绍了 ASP 内建对象 Response 的使用方法,在这一篇中作者将继续给大家介绍另两个非常实用且重要的 ASP 的内建对象 Application 和 Session. 在 ASP 的内建对象中除了用于发送.接收和处理数据的对象外,还有一些非常实用的代表 Active Server 应用程序和单个用户信息的对象. 让我们先来看看 Application 对象.在同一虚拟目录及其子目录下的所有 .asp 文件构成了 ASP 应用程序.我们非但可以使用 Applicat

ASP教程:第九篇 ASP内建对象Application 和 Session

 在上一篇中作者给大家详细介绍了 ASP 内建对象 Response 的使用方法,在这一篇中作者将继续给大家介绍另两个非常实用且重要的 ASP 的内建对象 Application 和 Session. 在 ASP 的内建对象中除了用于发送.接收和处理数据的对象外,还有一些非常实用的代表 Active Server 应用程序和单个用户信息的对象. 让我们先来看看 Application 对象.在同一虚拟目录及其子目录下的所有 .asp 文件构成了 ASP 应用程序.我们非但可以使用 Applica

ASP内建对象Application 和 Session

application|session|对象 作者: 书生 在上一篇中作者给大家详细介绍了 ASP 内建对象 Response 的使用方法,在这一篇中作者将继续给大家介绍另两个非常实用且重要的 ASP 的内建对象 Application 和 Session. 在 ASP 的内建对象中除了用于发送.接收和处理数据的对象外,还有一些非常实用的代表 Active Server 应用程序和单个用户信息的对象. 让我们先来看看 Application 对象.在同一虚拟目录及其子目录下的所有 .asp 文件

phalcon-入门篇4(log日志和session缓存)

phalcon-入门篇4(log日志和session缓存) 本教程基于phalcon2.0.9版本 前言 先在这里感谢各位phalcon技术爱好者,我们提供这样一个优秀的交流平台 在新年来临之际!在这里祝关注和喜欢phalcon和phalapi的童鞋们,有你们的支持我才有动力鼓起勇气为大家带来这一系列教程,那么今天的教程将是在猴年前的最后一篇了,我们今天的目的是了解phalcon的log机制以及session的使用,那么让我们在新年的喜悦中来一同学习今天的内容吧! 注:笔者水平有限,说的不正确的