HIbernate事物管理

主要解決的是個例問題:

髒讀:一個事務讀到另一個事務未提交的內容

       不可重複讀:一個事務讀到另一個事務已提交的內容(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>

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章