Hibernate:缓存

什么是缓存?它就是内存中的临时数据。

为什么使用缓存?减少和数据库交互的次数,从而提高查询效率。

适用缓存的数据:经常查询的,并且不经常修改的,同时数据一旦出现问题,对最终结果影响不大的。

不适用缓存的数据:

不管是否经常查询,只要经常修改的,都可以不用缓存;

并且如果数据由于使用缓存,产生了异常数据,对最终结果影响很大,则不能使用;

例如:股市的牌价、银行的汇率、商品的库存等等

一级缓存 :Session的缓存

它指的是Session对象的缓存,一旦Session对象销毁了,则一级缓存也就消失了

在同一session查询

第一次查询:先去数据库查询,并且把查询的结果存入了一级缓存之中,并且存到快照区。

第二次查询:先去一级缓存查询,如果存在则使用,如果不存在则去数据库查找。

一级缓存存储

快照机制

每次查找先比较缓存区和快照区是否相同,如果不同则先同步数据库

当使用save方法保存后也会在内存中有缓存数据,所以当进行大量数据的保存时可能会造成内存溢出错误

针对session中的缓存提供有三个处理的操作方法,这三个操作方法都在session的接口中定义:

flush方法的主要作用是清理缓存,强制数据库与Hibernate缓存同步,以保证数据的一致性。它的主要动作就是向数据库发送一系列的sql语句,并执行这些sql语句,但是不会向数据库提交。而commit方法则会首先调用flush方法,然后提交事务。这就是为什么我们仅仅调用flush的时候记录并未插入到数据库中的原因,因为只有提交了事务,对数据库所做的更新才会被保存下来。因为commit方法隐式的调用了flush,所以一般我们都不会显示调用flush方法。

二级缓存 :SessionFactory缓存

配置hibernate.cfg.xml文件

<!-- 在配置文件中打开二级缓存 -->
<property name="cache.use_second_level_cache">true</property>
<!-- 配置二级缓存的处理类 -->
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>

导入ehcache的jar文件

在工程src目录下创建ehcache的配置文件:ehcache.xml,path路径找不到会导致报错

<ehcache>
    <diskStore path="c:/hibernateCache"/>
    <defaultCache
        maxElementsInMemory="10"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"/>
        
    <cache name="org.haiwen.entity.Goods"
        maxElementsInMemory="10"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"/>
</ehcache>

对一个实体类进行缓存配置,需要在此类对应的Xxx.hbm.xml文件里面进行缓存配置

<cache usage="read-write"/>
或者
<class-cache usage="read-write" class="org.haiwen.entity.Goods"/>

在实体类上注解使用二级缓存,报错是因为导包不对

@Entity
@Table(name = "goods")
@Cacheable(value = true)
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class Goods {

测试

public void list() {
	Configuration cfg = new Configuration().configure();
	SessionFactory factory = cfg.buildSessionFactory();
	Session session = factory.getCurrentSession();
	session.getTransaction().begin();
	List<Goods> goods = session.createCriteria(Goods.class).list();
	for (Goods good : goods) {
		System.out.println(good.getGoodsName());
	}
	session.getTransaction().commit();

    //以下查询不会发送SQL
	Session session2 = factory.getCurrentSession();
	session2.getTransaction().begin();
	Goods goods2 = (Goods) session2.get(Goods.class, 1);
	System.out.println(goods2.getGoodsName());
	session2.getTransaction().commit();
}
发布了202 篇原创文章 · 获赞 37 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/lovecuidong/article/details/100133797