- 修改持久化对象的属性值,并不会立即发送SQL语句,而是提交事务之前,执行flush操作的时候才会发送相应的UPDATE语句。
- 发送UPDATE语句时,数据的修改并不会立即生效,只有提交了事务之后,数据的修改才会永久的保存下来。
操作
flush:推送。将缓存中数据的改变落实到数据库中
refresh:刷新。将数据库中数据的改变提取到缓存中
clear:清空。清空Session缓存
Session对象默认在什么情况下执行flush操作?
显式调用Session的flush()方法
调用Transaction对象的commit()方法时,先flush缓存,在提交事务
执行HQL、QBC查询之前,先flush缓存,保证HQL或QBC查询到的数据是最新的。
refresh操作与事务隔离级别
refresh()方法读取到的数据是不是真正的最新数据,需要参照当前的事务隔离级别
一级缓存
一级缓存:又称为session级别的缓存。当获得一次会话(session),hibernate在session中创建多个集合(map),用于存放操作数据(PO对象),为程序优化服务,如果之后需要相应的数据,hibernate优先从session缓存中获取,如果有就使用;如果没有再查询数据库。当session关闭时,一级缓存销毁。
一级缓存快照:与一级缓存存放位置是一样,对一级缓存数据备份。保证数据库的数据与一级缓存的数据必须一致。如果一级缓存修改了,在执行commit提交时,将自动刷新一级缓存,执行update语句,将一级缓存的数据更新到数据库。
二级缓存
Hibernate维护了两个级别的缓存,一个是线程级别的一级缓存,一个是进程级别的二级缓存。其中一级缓存是由Session对象维护的,二级缓存是由SessionFactory维护的。
Web应用中的进程和线程
在Web应用中Servlet容器也就是服务器的运行对应一个大的进程,而具体每一个请求的处理则是由线程执行的。所以线程级别的一级缓存只能在当前请求处理过程中可用,线程结束就释放了,存在时间很短;而二级缓存工作在进程级别所以只要服务器还在运行就一直有效。
SessionFactory的缓存分类
- 内置缓存:Hibernate自带的,不可卸载。通常在Hibernate的初始化阶段,Hibernate会把映射元数据和预定义的SQL语句放到 SessionFactory的缓存中。映射元数据是映射文件中数据(.hbm.xml文件中的数据)的复制。该内置缓存是只读的。
- 外置缓存(二级缓存):由可配置的缓存插件维护。在默认情况下,SessionFactory不会启用这个缓存插件。外置缓存中的数据是数据库数据的复制,外置缓存的物理介质可以是内存或硬盘。
数据要求
适合存入二级缓存的数据
- 很少被修改,经常被查询
- 不重要,允许出现偶尔的并发问题
不适合存入二级缓存的数据
- 经常被修改的数据:会由于更新不及时导致二级缓存中的数据总是错误的
- 财务数据,不允许任何的并发问题
- 与其他应用程序共享的数据
二级缓存架构
并发访问策略
- 非严格读写(Nonstrict-read-write):不保证缓存与数据库中数据的一致性。提供Read Uncommited事务隔离级别,对于极少被修改,而且允许脏读的数据,可以采用这种策略
- 读写型(Read-write):提供Read Commited数据隔离级别。对于经常读但是很少被修改且不允许脏读的数据,可以采用这种隔离类型。
- 事务型(Transactional):仅在受管理环境下适用。它提供了Repeatable Read事务隔离级别,可以防止脏读和不可重复读。
- 只读型(Read-Only):提供Serializable数据隔离级别,对于从来不会被修改的数据,可以采用这种访问策略
并发访问策略 | 隔离级别 |
Nonstrict-read-write | Read Uncommited |
Read-write | Read Commited |
Transactional | Repeatable Read |
Read-Only | Serializable |