Hibernate缓存
Hibernate一级缓存
Hibernate一级缓存默认就是存在的,一级缓存就是Session对象维护的一个Map键值对集合。
Session缓存的作用
减少访问数据库的频率
- 应用程序从内存中读取持久化对象的速度显然要比到数据库中查询数据的速度快多了,因此session的缓存可以提高数据访问的性能。
验证
...... trans=session.beginTransaction(); /*第一次查询*/ Student student = (Student)session.get(Student.class, 1L); System.out.println(student); /*第一次查询*/ student = (Student)session.get(Student.class, 1L); System.out.println(student); ......
运行结果
Hibernate : select ...... Student [.....] Student [.....]
我们可以看出,两次查询相同的一条记录,只输出了一条select查询语句,因此第二次查询并未访问数据库,而是在Session缓存中查询出来的。使用get()方法将数据记录从数据库中查询出来,并将对象变为持久化对象,在缓存中保存了OID和对象的引用,第二次查询只通过OID查询缓存查询已有信息。
dirty-check(脏检查)
保证缓存中的对象和数据库中的相关记录保存时刻同步
当缓存中的持久化对象的状态发生了变化,Session并不会立即执行相关的SQL语句,这使得Session能够把几条相关的SQL语句合并为一条SQL语句,以减少访问数据库的次数,从而提高应用程序的性能
例如,我们将学生信息从数据库中查询出来,在使用update()方法更新其姓名,不做事务的提交,再使用update()方法更新其年龄,这时才做事务的提交。SQL语句的输出我们可以发现,只执行了一次select的SQL语句和一次update的SQL语句。
- 当session加载了某个对象后,会为该对象复制一份快照。当Session清理缓存时,会比较当前对象的属性值和快照中的属性值,的变化情况来决定是否要同步数据库。
这份快照实际上就是加载时对象的另一份拷贝,当持久化对象改变时快照的内容并不会改变,而清理缓存时,如果对象的属性值和快照的不一致,那么将会同步数据库
当缓存中的持久化对象之间存在循环关联关系时,Session会保证不出现访问对象的死循环,以及由死循环引起的JVM堆栈的溢出。
一级缓存的清空与清理
session的清空
- 当调用Session的clear()方法时,清空Session的缓存
Session的清理缓存
- 当应用程序commit()时,先清理缓存,然后再向数据库提交
清理缓存主要是先判断Session关联的持久化对象和快照里的备份的对象是否发生改变,如果改变,再向数据库提交事务,同步数据库。
当调用Session的查询方法(query等,而非get或load方法)时,如果持久化对象属性发生了变化,就会先清理缓存,以保证查询结果能放映持久化对象的最新状态。
当应用程序显式地调用Session的flush()方法时(强制清理缓存)
...... trans=session.beginTransaction(); Student student = (Student)session.get(Student.class, 1L); System.out.println(student); //改变信息 student.setAddress("shanghai"); student.setAge(19); //不调用update方法 //session.update(student); trans.commit(); ......
在上面一段程序里,我们即使不调用update方法,事务提交前会先清理缓存,比较持久化对象和备份的快照是否一致,如果发生改变,则和数据库同步,所以虽然没有调用update方法,还是会执行update SQL语句,如果我们再执行一下程序,此时我们查找出来的学生信息(Address:shanghai;Age:19)和快照里的信息都已经修改,即便是再修改(实际上属性值并未改变),也不会再执行update语句,因为和快照里的信息并无两样。
session.flush()也可以清理缓存,也将持久化对象会同步数据库,实际上commnit()方法就已经先做了flush操作。
设定Session清理缓存的时间点
Session的setFlushMode()方法用于设定清理缓存的时间点。FlushMode类定义了三种不同的清理模式:FlushMOde.AUTO(默认值)、FlushMode.COMMIT和Flush.NEVER。
清理缓存的模式 查询方法 commit()方法 flush()方法 FlushMOde.AUTO 清理 清理 清理 FlushMode.COMMIT 不清理 清理 清理 Flush.NEVER 不清理 不清理 清理