- 一级缓存: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 = ...
//当我们再查询时,缓存中数据就不是当前数据了
//检查时间戳,