Session 的缓存(一级缓存):
我们知道在 JVM 中,如果一个对象被还被其它域引用,那么这个对象的生命周期就不会结束,Java的
垃圾清理器就不会清理该对象所占用的内容空间。
在Hibernate中,Session维护了很多集合,其中就会把当前持久化的对象保存在一个集合中。
Person p = new Person("Jenney", 20);
session.save(p); // 持久化操作:Session将会把这个 Person 对象存入集合中。
id = p.getId();
当我们下次再操作该对象时,我们就可以从内存中把它拿出来,这样就减少了与数据库打交道的机会,从而
提高了性能。
Person p = session.load(Person.class, id); // 从Session的缓存中加载该对象
那么,什么时候这个集合会被清空呢?当我们调用 Session.commit(); 方法的时候,Session的缓存将被
清空。
Session的缓存有两大作用:
(1):减少数据库访问的频率
(2):保证缓存中的对象与数据库记录保持同步,位于缓存中的对象始终与数据库记录保持一致,
所以该对象称为持久化对象。
当缓存中对象的属性发生了改变,Session不会立即同步到数据库(立即执行SQL语句),
这使得Session能够把几条相关的SQL语句合并为一条。以便减少对数据库的访问,提高应用程序性能。
例如:
Person p = new Person();
p.setName("a");
p.setName("b");
session.commit();
当Session在清理缓存时,只生成了一条SQL语句 :update Person set name='b' where id = ?
当Session加载了对象时,Session会为该对象值类型的属性设置一份快照,当清理缓存时,就会去比较
快照中的对象与当前对象哪些值类型的属性发生了改变,并生成SQL语句。
那么 Session 到底是在什么情况下才会清理内存,生成SQL语句呢?
默认情况下,Session会在以下时间点清理缓存:
(1):当调用session.commit()方法时,Session会先 清理缓存 ,然后 commit 事物。
(2):当调用 session.find() / session.iterate() 方法时,Session会先清理缓存,以保证查询出来
的持久化对象是最新的状态。
(3):当调用 session.flush() 方法的时候,该方法就是清理缓存的方法。
注意:flush 方法是清理缓存的方法,但它不会提交事物。而commit方法会先调用flush方法清理缓存,然后
才会提交数据库事物。
当然,我们也可以手动设置Session的清理缓存的模式。session.setFlushMode(FlushMode);方法用于设置
Session的清理缓存模式。 Session 清理缓存的模式有三种
FlushMode.AUTO 默认方式,会在每次执行查询操作前清理缓存。
FlushMode.COMMIT 在提交事物时 先清理缓存再提交事物
FlushMode.NEVER 只在 显示调用 session.flush(); 方法时清理缓存。
如果,一个事物中仅仅只有查询数据库的操作而没有修改数据库数据的操作,我们就可以使用 COMMIT 模式,
这样可以避免Session在查询数据库的时候清理缓存,可以稍微提高应用程序的性能。
在多数情况下,我们不需要显示的调用 flush 方法。flush方法适用于以下场合:
(1)在持久化某个对象时会引发数据库中的触发器,这时我们显示的调用 flush 方法就可以及时的更新
到数据库并引发触发器执行相关联的操作。
(2)在应用程序中混合使用 Hibernate 和 JDBC 时,需要及时清理缓存以避免和 JDBC 操作发生冲突。