- 一級緩存: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 = ...
//當我們再查詢時,緩存中數據就不是當前數據了
//檢查時間戳,