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

简介: <div class="markdown_views"><h1 id="java对象在jvm中的存活条件">java对象在JVM中的存活条件</h1><p>在java中,我们使用<code>User user = new User();</code>来创建一个java对象时,JVM会为其分配一块内存空间,此时,这个对象被变量“user”引用,那么它就会一直存在于内存中,而

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语句。

目录
相关文章
|
3月前
|
SQL Java 数据库连接
Hibernate 是一款开源 ORM(对象关系映射)框架,封装了 JDBC,允许以面向对象的方式操作数据库,简化了数据访问层的开发。
Hibernate 是一款开源 ORM(对象关系映射)框架,封装了 JDBC,允许以面向对象的方式操作数据库,简化了数据访问层的开发。通过映射机制,它可以自动处理对象与数据库表之间的转换,支持主流数据库,提高了代码的可移植性和可维护性。其核心接口包括 SessionFactory、Session 和 Transaction 等,通过它们可以执行数据库的 CRUD 操作。配置方面,需在项目中引入 Hibernate 及数据库驱动依赖,并创建 `hibernate.cfg.xml` 配置文件来设置数据库连接和 Hibernate 行为参数。
43 1
|
3月前
|
Java 数据库连接 数据库
告别繁琐 SQL!Hibernate 入门指南带你轻松玩转 ORM,解锁高效数据库操作新姿势
【8月更文挑战第31天】Hibernate 是一款流行的 Java 持久层框架,简化了对象关系映射(ORM)过程,使开发者能以面向对象的方式进行数据持久化操作而无需直接编写 SQL 语句。本文提供 Hibernate 入门指南,介绍核心概念及示例代码,涵盖依赖引入、配置文件设置、实体类定义、工具类构建及基本 CRUD 操作。通过学习,你将掌握使用 Hibernate 简化数据持久化的技巧,为实际项目应用打下基础。
133 0
|
3月前
|
Java 数据库连接 数据库
|
3月前
|
Java 数据库连接 数据库
|
3月前
|
缓存 安全 Java
|
3月前
|
缓存 安全 Java
Hibernate 中的 Session 是线程安全的吗?
【8月更文挑战第21天】
38 0
|
3月前
|
缓存 安全 Java
Hibernate 中的 Session 是什么?
【8月更文挑战第21天】
19 0
|
5月前
|
缓存 Java 数据库连接
解析Hibernate与JPA:Java对象的数据库化之旅
【6月更文挑战第25天】在Java企业开发中,Hibernate和JPA提供优雅的数据持久化方案。Hibernate是JPA规范的强大ORM实现,简化对象与数据库映射。配置环境后,通过@Entity注解定义实体类映射表,如`User`类映射&quot;users&quot;表。利用JPA的EntityManager执行查询和更新,如JPQL查询及对象更新。事务管理和性能优化是关键,确保数据完整性和应用性能。本文揭示了Hibernate与JPA的最佳实践,助开发者从容应对数据持久化。
42 0
|
5月前
|
存储 Java 数据库连接
深入探索Hibernate与JPA:Java对象与数据库表的桥梁
【6月更文挑战第25天】Java ORM如Hibernate和JPA简化了数据库交互。在电商系统案例中,JPA注解如`@Entity`、`@Table`、`@Id`定义了对象-表映射。Hibernate利用这些定义实现持久化,如`Session.save()`保存用户对象至数据库,降低了复杂性并提升了开发效率。
46 0