主要解決的是個例問題:
髒讀:一個事務讀到另一個事務未提交的內容
不可重複讀:一個事務讀到另一個事務已提交的內容(insert)
虛讀(幻讀):一個事務讀到另一個事務已提交的內容(update)
解決這三個問題的級別:
read uncommittd,讀未提交。存在3個問題。
readcommitted,讀已提交。解決:髒讀。存在2個問題。
repeatableread ,可重複讀。解決:髒讀、不可重複讀。存在1個問題。
serializable,串行化。單事務。沒有問題。
樂觀鎖:
就是再起POJO對象中加一個version字段,表示其版本號,類型是Integer
在*.hbm.xml文件中配置<version name="...">
public class Customer {
private Integer id;
private String cname;
//表示客戶與訂單之間的一對多關係
private Set<Order> orderSet=new HashSet<Order>();
private Integer version;
<version name="version"></version>
hibernate的二級緩存
hibernate的二級緩存是SessionFactory級別的緩存。
hibernate二級緩存操作配置:
1.導入jar包:ehcache-1.5.0.jar/commons-logging.jar/ backport-util-concurrent.jar
2.開啓二級緩存(我要使用二級緩存)
3.確定二級緩存提供商(我要使用哪個二級緩存)
4.確定需要緩存內容
導入jar包:
ehcache-1.5.0.jar是二級緩存的核心包,commons-logging.jar/和backport-util-concurrent.jar都是其依賴包
開啓二級緩存:
<property name="hibernate.cache.use_second_level_cache">true</property>
配置二級緩存提供商:
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
緩存內容配置:
<!-- 類緩存配置 -->
<class-cache usage="read-only" class="com.study.hibernate.Customer"/>
<class-cache usage="read-only" class="com.study.hibernate.Order"/>
<!--集合緩存設置-->
<collection-cache usage="read-only" collection="com.study.hibernate.Customer.orderSet"/>
類緩存測試:
@Test
public void test8(){
Session session=HBUtils.getSession();
//開啓事物
Transaction tr = session.beginTransaction();
Customer customer1 = (Customer) session.get(Customer.class, 6);
session.clear();//清楚一級緩存
Customer customer2 = (Customer) session.get(Customer.class, 6);
System.out.println(customer1==customer2);
//提交事物
tr.commit();
//關閉會話
session.close();
}
上述測試如果打印兩次sql語句,那麼二級緩存失效,如果打印一次,則二級緩存起作用。
測試結果:打印一次 但是比較結果是false
類緩存存儲的不是類對象,而是散列碼,所以,當有數據要查詢的時候,查看二級緩存中有無此數據,如果有,則把該數據組裝成對象,然後返回。
集合緩存測試:
@Test
public void test9(){
Session session=HBUtils.getSession();
//開啓事物
Transaction tr = session.beginTransaction();
Customer customer1 = (Customer) session.get(Customer.class, 6);
for(Order o:customer1.getOrderSet()){
System.out.println(o);
}
session.clear();//清楚一級緩存
Customer customer2 = (Customer) session.get(Customer.class, 6);
for(Order o:customer2.getOrderSet()){
System.out.println(o);
}
//提交事物
tr.commit();
//關閉會話
session.close();
}
集合緩存存儲的不是集合,而是id的值,所以在二級緩存中取數據的時候,是取到的id,然後再去類緩存中去數據。
時間戳測試:
假如我們在一次查詢後,更改了其數據庫中的數據,那麼它是怎麼
@Test
public void test10() {
Session session = HBUtils.getSession();
// 開啓事物
Transaction tr = session.beginTransaction();
Customer customer1 = (Customer) session.get(Customer.class, 6);
System.out.println(customer1.getCname());
session.createQuery("update Customer set cname=:cname where id=:id")
.setParameter("cname", "pe").setParameter("id", 6)
.executeUpdate();
// 提交事物
tr.commit();
// 關閉會話
session.close();
Session session1 = HBUtils.getSession();
// 開啓事物
Transaction tr1 = session1.beginTransaction();
Customer customer2 = (Customer) session1.get(Customer.class, 6);
System.out.println(customer2.getCname());
// 提交事物
tr1.commit();
// 關閉會話
session1.close();
}
查詢緩存:
查詢緩存默認不使用。需要手動開啓
查詢緩存:將HQL語句與 查詢結果進行綁定。通過HQL相同語句可以緩存內容。
默認情況Query對象只將查詢結果存放在一級和二級緩存,不從一級或二級緩存獲取。
查詢緩存就是讓Query可以從二級緩存獲得內容
要使用查詢緩存,則必須開啓查詢緩存
<!--開啓查詢緩存 -->
<property name="hibernate.cache.use_query_cache">true</property>
@Test
public void test11() {
Session session = HBUtils.getSession();
// 開啓事物
Transaction tr = session.beginTransaction();
Query query=session.createQuery("from Customer");
query.setCacheable(true); //從二級緩存中取數據,取不到就查詢數據,並且把數據放到二級緩存中
List<Customer> cusList=query.list();//查詢所有的數據
for(Customer c:cusList){
System.out.println(c.getCname());
}
// 提交事物
tr.commit();
// 關閉會話
session.close();
Session session1 = HBUtils.getSession();
// 開啓事物
Transaction tr1 = session1.beginTransaction();
Query query1=session1.createQuery("select c from Customer c");//不同的hql語句,從二級緩存中獲取
query1.setCacheable(true);
List<Customer> cusList1=query1.list();//查詢所有的數據
for(Customer c:cusList1){
System.out.println(c.getCname());
}
// 提交事物
tr1.commit();
// 關閉會話
session1.close();
}
測試結果:打印一次語句,可以看到上述的技術hql不同,但轉換成的sql語句相同,所以只打印一次。
所以,查詢緩存中根據sql語句判斷對否相同。
ehcache文件配置:
在使用二級緩存的時候,可以配置一些參數來優化二級緩存
默認的配置文件:ehcahe-1.5.0.jar//ehcache-failsafe.xml文件中,主要的配置項如下:
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
我們現在要更改其文件配置,只需在src下創建一個名爲ehcache.xml的文件
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<diskStore path="D:/ehcache"/> <!-- 二級緩存文件的存放位置 -->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
</ehcache>