摘自网络: Hibernate中的一级缓存的底层是以Map形式存在的,key是主键,value是对象,所以它的泛型为Map<Serializable,Object>,key的泛型为串行化是因为主键都可被序列化。简单说完一级缓存的底层原理,下面开始讲快照问题。 当程序调用get()方法时,Session会先在缓存区找有没有存在对应的对象,如果是第一次调用,这时缓存区是空的,自然就找不到,那么Session就会发送select语句向数据库查找,数据找到后将结果返回给Session,这时Session会对数据进行组装成实体对象,并且一式两份,即一份在缓存中,一份是快照,然后Session会将缓存中的那一份返回给程序;如果这时进行更新操作,那么在Session中会进行对比缓存中的对象与快照中的对象,如果对象的属性发生了变化,那么就会发送update语句对数据库进行更新,如果对象的属性没有变化,则不发送update语句。 总结,快照是数据库的数据在Session中的代表,也就是说,数据库中的数据一旦发生变化,快照就会随之改变。个人觉得这样设计能减少对数据库的访问,提高数据库的效率。
hibernate存在2个缓存 第一级别的缓存是 Session 级别的缓存,它是属于事务范围的缓存(session的一级缓存) 第二级别的缓存是 SessionFactory 级别的缓存,它是属于进程范围的缓存(二级缓存 session的一级缓存 使用hibernate进行查询的时候,将查询结果放置到session的一级缓存中,在一级缓存中存在对象,对象使用属性的OID的值进行区分,此时再使用相同的OID进行查询的时候,首先会在session一级缓存中进行查找是否存在相同的OID 如果存在相同的OID,此时不再查询数据库,而是直接使用一级缓存中存在的对象 如果没有存在相同的OID,此时再查询数据库,将查询得到的结果数据再放置到session一级缓存中 目的:减少访问数据库的次数 session的快照 使用id进行查询数据库,将查询得到的结果放置到session一级缓存中,同时复制一份数据,放置到session的快照中 当使用tr.commit()的时候,同时清理session的一级缓存(flush) 当清理session一级缓存的时候,会使用OID判断一级缓存中对象和快照中的对象进行比对 如果2个对象(一级缓存的对象和快照的对象)中的属性发生变化,则执行update语句,此时更新数据库,更新成一级缓存中的数据 如果2个对象中的属性不发生变化,此时不执行update语句 目的:确保和数据库中的数据一致 Session二级缓存 一个可配置的缓存插件,包括类级别的缓存区域,集合级别的缓存区域,查询级别的缓存区域,时间戳级别的缓存区域 其使用步骤大致如下: 1 拷贝ehcache-1.5.0.jar到当前工程的lib目录下 2 开启二级缓存 <property name="hibernate.cache.use_second_level_cache">true</property> 3 要指定缓存的供应商 <property name="hibernate.cache.provider_class"> org.hibernate.cache.EhCacheProvider</property> 4 指定使用二级缓存的类 方法一 在使用类的*.hbm.xml配置 选择需要使用二级缓存的持久化类, 设置它的二级缓存的并发访问策略, <class> 元素的 cache 子元素表明 Hibernate 会缓存对象的简单属性, 但不会缓存集合属性, 若希望缓存集合属性中的元素, 必须在 <set> 元素中加入 <cache> 子元素 方法二 在hibernate.cfg.xml文件中配置(建议) <!-- 指定使用二级缓存的类放在maping下面 --> <!-- 配置类级别的二级缓存 --> <class-cache class="cn.itcast.c3p0.Customer" usage="read-write"/> <class-cache class="cn.itcast.c3p0.Order" usage="read-write"/> <!-- 配置集合级别的二级缓存 --> <collection-cache collection="cn.itcast.c3p0.Customer.orders" usage="read-write"/> 5 配置ehcache默认的配置文件ehcache.xml(名字固定)(放在类路径下) hibernate中一级缓存、快照、二级缓存面试的时候问得比较多。
原文地址:https://www.cnblogs.com/Danial7777777/p/9348210.html
时间: 2024-10-20 14:59:46