Hibernate二级缓存

  • 一级缓存:session级别缓存,一次请求中共享数据
session就是连接,有很多的session,并发时没人一个session。

所以一个session一个一级缓存

默认就存在
所以session就是线程级别的,每个session都有自己的缓存
  • 二级缓存:
二级缓存就一个:
    SessionFactory

    不是默认就有的
所以是进程级别的
    也是在内存中

那么什么数据放在二级缓存中?

1.经常使用的数据

2.不经常被修改

以上两点需要同时满足
那么为什么呢?
因为多个session同时访问,出现并发问题。
使用二级缓存的好处?
1.提高访问数据的速度。
2.不用通过网络获取数据,节省网络资源
例如:
买票:省,市,县

    如果是Android用xml解析
    那么web端,满足以上两个要求,就可以放在二级缓存中。

二级缓存提供商

我们在这里使用ehcache

导入jar包
然后

<!-- 开启二级缓存-->
//hibernate.properties

//hibernate.cache.use_second_level_cache=true
<!--配置使用二级缓存-->
<property name="hibernate.cache.provider_class">org.hibernate.cache.EHCacheProvider</property>
类缓存区、集合缓存区、查询缓存区、时间戳缓存区
类缓存区:放入查询的对象


1.先配置
    <!--配置类缓存区缓存的类类型,放在mapping之后-->
    <class-cache usage="read-only" class="domain.Customer"/>


//test.java

session.get(Customer.class,1);
//会发送select到数据库,查询出的数据被封装成对象放入一级缓存,
//还会放入二级缓存

session.clear()//清空一级缓存

session.get(Customer.class,1);
//我们在这里查看有没有打印select语句,如果没有,说明从二级缓存中取得数据

从debug可以看出,没有输出select语句,那么说明是从二级缓存中取得数据


清空一级缓存后在从缓存中取,应该是同一个对象,理论上应该输出true

其实真实情况是:
    输出为false,说明了类缓存区,存的不是整个对象,存的是对象的散列数据
    当我们查询时,取出数据,再封装成新的对象。所以这时候,两个对象不一样了。


另外:每次session.clear();  
    清空的是上一步的一级缓存,如果再get,就又生成新的一级缓存
集合缓存区:
<!--需要配置Order类-->
<class-cache usage="read-only" class="domain.Order"/>
<!--配置集合缓存区缓存的集合-->
<collection-cache usage="read-only" collection="Customer.orders"></>
//test.java

session.get(Customer.class,1);
//注意:默认关联订单是懒加载,所以不会查询   
//先使用一下
for(Order order:cus.getOrders()){
    System.out.print(order.getName());
}
session.clear();

//从类缓存区中取
get(Customer.class,1);
//从集合缓存区取
for(Order order:cus.getOrders()){
    System.out.print(order.getName());
}

通过debug看出直接从二级缓存中取,没有发送select

那么集合缓存区怎么存的集合?
我们先把 <class-cache  order  这个配置去掉

然后通过迭代器遍历,

Iterator<Order> ite = cus.getOrders().iterator();
//当执行到这一步,又重新发送了select语句
//并且是通过orderid查的

这说明集合缓存区缓存的是订单id
那么正常的执行步骤应该是这样的:
当使用时,先拿id去类缓存区查找,如果没找到,
再去数据库根据订单id查询

查询缓存区:hql使用的缓存区

配置过程:

//1.开启查询缓存区
<property name="hibernate.cache.use_query_cache">true</property>
//test.java
Query query = session.createQuery("from Customer");
query.setCacheable(true);//使用二级缓存
List<Customer> list = query.list();
数据放入了类缓存区,查询缓存区还是存储id
时间戳缓存区
最后操作时间
t_customer 2016-10-10 12.12.12
那么这有什么用?
比如说我们先查询:
    cus = ...
    //time1

    session.createQuery("update t_customer set name="wang" where id=8");
    session.clear();
    cus = ...
    //当我们再查询时,缓存中数据就不是当前数据了
    //检查时间戳,
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章