我一直在浏览hibernate文档,讨论二级缓存和查询缓存,并留下有关二级缓存同步到DB的问题,反之亦然。每个会话都可以定义自己的缓存模式,如NORMAL,GET,PUT和REFRESH。将2L缓存< - >在所有情况下都会发生数据库同步,如果是这样的话会发生什么? 非常感谢。
答案 0 :(得分:4)
来自海洋的堕落
谈论二级缓存,直接进入
usage-指定缓存策略:transactional,read-write, 非严格读写或只读
就实体缓存而言,创建/更新/删除操作的预期调用序列是:
删除:
lock(java.lang.Object, java.lang.Object)
evict(java.lang.Object)
release(java.lang.Object, org.hibernate.cache.CacheConcurrencyStrategy.SoftLock)
更新:
lock(java.lang.Object, java.lang.Object)
update(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object)
afterUpdate(java.lang.Object, java.lang.Object, java.lang.Object,org.hibernate.cache.CacheConcurrencyStrategy.SoftLock)
INSERTS:
insert(java.lang.Object, java.lang.Object, java.lang.Object)
afterInsert(java.lang.Object, java.lang.Object, java.lang.Object)
就集合缓存而言,所有修改操作实际上只会使条目无效。此处的调用顺序为:
lock(java.lang.Object, java.lang.Object)
evict(java.lang.Object)
release(java.lang.Object, org.hibernate.cache.CacheConcurrencyStrategy.SoftLock)
Nonstrict-R / w和R / W缓存
每当会话开始时,都会添加一个时间戳。(ST) 只要在缓存中加载了一个项目,就会向其添加一个时间戳。(CT) 如果ST< CT,意味着会话比缓存的项目早,那么如果我们在这个较旧的会话中查找缓存的项目,Hibernate 不会查看缓存。相反,它总是会看到 数据库,并因此重新加载缓存中的项目 时间戳。
非严格读写
•永远没有锁定。
•因此,当对象实际在数据库中更新时,在提交时(直到数据库完成提交),缓存具有旧对象,数据库具有新对象。
•现在,如果任何其他会话查找该对象,它将查找缓存并找到旧对象。(DIRTY READ
)
•但是,提交完成后,对象将从缓存中逐出,以便查找对象的下一个会话必须查看数据库。
用于读写
•只要有人试图更新/删除某个项目,该项目就会在缓存中软锁定,这样,如果任何其他会话尝试查找该项目,则必须转到该数据库。
•现在,一旦更新结束并且数据已提交,将使用新数据刷新缓存并释放锁定,以便其他事务现在可以在CACHE中查找而不必转到数据库。
•因此,没有Dirty Read的可能性,任何会话几乎都会从数据库/缓存中读取READ COMMITTED数据。
总结:
ReadOnly cache
只能执行读取和插入操作,无法执行 更新/删除。表现最快。
Nonstrict Read Write Cache
不会使用任何锁,所以 总是有可能脏读。然而,它总是驱逐出境 从缓存中输入,以便任何后续的sesssions始终引用 DB。
Read Write cache
首先使用锁,但采用异步方式 插入/更新/删除发生在tx中。当缓存条目是 softlocked和其他会话必须引用数据库。一旦 TX。完成后,锁被释放,缓存就是 更新。(交易之外)。在某些情况下,可重复读取 可能会受到损害。
Transactional caches
显然更新了数据库和缓存 在同一个交易中,所以它始终处于一致状态 尊重数据库。
Entity type
主要是更新并且已经并发读取和 更新,读写缓存策略可能不是很有用 读取将被偏转到数据库
查询缓存
需要在hibernate.cfg.xml中启用以下属性 1
真
此设置会创建两个新的缓存区域:
org.hibernate.cache.StandardQueryCache
,持有缓存的查询结果
org.hibernate.cache.UpdateTimestampsCache
,保存可查询表的最新更新的时间戳。这些用于验证结果,因为它们是从查询缓存中提供的。
Query cache
不会缓存缓存中实际实体的状态;它仅缓存标识符值和值类型的结果。因此,对于那些希望作为查询结果缓存的一部分进行缓存的实体,查询缓存应始终与二级缓存一起使用