1. 程式人生 > >Java事務管理之Hibernate

Java事務管理之Hibernate

環境與版本

Hibernate 版本:Hibernate 4.2.2 (下載後的檔名為hibernate-release-4.2.2.Final.zip,解壓目錄hibernate-release-4.2.2.Final)
資料庫: oracle 10g

匯入lib\required 中的所有jar 包

理論說明

1.SessionFactory負責建立Session,SessionFactory是執行緒安全的,多個併發執行緒可以同時訪問一個SessionFactory 並從中獲取Session例項
2.Session作為貫穿Hibernate的持久化管理器核心,提供了眾多的持久化的方法,如save(), update ,delete ,find(Hibernate 3中已經取消了此方法)等,通過這些方法我們可以透明的完成物件的增刪改查(CRUD-- create read update delete),這裡所謂的透明是指,Session在讀取,建立和刪除影射的實體物件的例項時,這一系列的操作將被轉換為對資料庫表中資料的增加,修改,查詢和刪除操作。
Session有以下的特點
  1)不是執行緒安全的,應該避免多個執行緒共享同一個Session例項 
  2)Session例項是輕量級的,所謂輕量級:是指他的建立和刪除不需要消耗太多資源 
  3)Session物件內部有一個快取,被稱為Hibernate第一快取,他存放被當前工作單元中載入的物件,每個Session例項都有自己的快取。


3.Hibernate Session快取被稱為Hibernate的第一級快取。SessionFactory的外接快取稱為Hibernate的二級快取。這兩個快取都位於持久層,它們存放的都是資料庫資料的拷貝。SessionFactory的內建快取 存放元資料和預定義SQL, SessionFactory的內建快取是隻讀快取。


4. Hibernate Session快取的三大作用:
1)減少資料庫的訪問頻率,提高訪問效能。
2)保證快取中的物件與資料庫同步,位於快取中的物件稱為持久化物件。
3)當持久化物件之間存在關聯時,Session 保證不出現物件圖的死鎖。
Session 如何判斷持久化物件的狀態的改變呢?
Session 載入物件後會為物件值型別的屬性複製一份快照。當Session 清理快取時,比較當前物件和它的快照就可以知道那些屬性發生了變化。


5. Session 什麼時候清理快取?
1)commit() 方法被呼叫時
2)查詢時會清理快取,保證查詢結果能反映物件的最新狀態。
3)顯示的呼叫session 的 flush方法。
session 清理快取的特例:
當物件使用 native 生成器 時 會立刻清理快取向資料庫中插入記錄。

例項程式碼

測試的程式碼目錄如下:

hibernate.cfg.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>  
    <session-factory>  
        <property name="show_sql">true</property>  
        <property name="hibernate.connection.driver_class">  
            oracle.jdbc.driver.OracleDriver  
        </property>  
        <property name="hibernate.connection.url">  
            jdbc:oracle:thin:@XX.26.158.43:1521:orcl 
        </property>  
        <property name="hibernate.connection.username"></property>  
        <property name="hibernate.connection.password"></property>  
        <property name="dialect">org.hibernate.dialect.OracleDialect</property>  
          
        <mapping resource="com/oscar999/trans/hibernate/Product.hbm.xml"/>  
    </session-factory>  
</hibernate-configuration>  

Product.java
/**   
 * @Title: Product.java
 * @Package com.oscar999.trans.hibernate
 * @Description:
 * @author XM
 * @date Feb 15, 2017 1:44:47 PM
 * @version V1.0   
 */
package com.oscar999.trans.hibernate;

import java.io.Serializable;

/**
 * @author XM
 * 
 */
public class Product implements Serializable {

	public Product() {
	}

	private Integer id;

	private String name;

	private String price;

	private static final long serialVersionUID = 1L;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPrice() {
		return price;
	}

	public void setPrice(String price) {
		this.price = price;
	}

}

Product.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping SYSTEM "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
	<class name="com.oscar999.trans.hibernate.Product" table="TEST_PRODUCT">
		<id name="id" column="id" type="java.lang.Integer">
			<generator class="assigned" />
		</id>
		<property name="name" column="name" type="java.lang.String"
			not-null="true" unique="true" length="20" />
		<property name="price" column="price" type="java.lang.String"
			not-null="false" unique="false" length="20" />
	</class>
</hibernate-mapping>


TestMain.java

/**   
 * @Title: TestMain.java
 * @Package com.oscar999.trans.hibernate
 * @Description: 
 * @author XM
 * @date Feb 15, 2017 2:02:17 PM
 * @version V1.0   
 */
package com.oscar999.trans.hibernate;

import java.io.File;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

/**
 * @author XM
 * 
 */
public class TestMain {

	/**
	 * @param args
	 */

	public Session getSession() {
		Session session = null;
		Configuration conf = new Configuration().configure(new File("src/com/oscar999/trans/hibernate/hibernate.cfg.xml"));
		ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(conf.getProperties()).buildServiceRegistry();
		SessionFactory sf = conf.buildSessionFactory(serviceRegistry);
		session = sf.openSession();
		return session;
	}

	public void addProduct(Session session, String name, String price) {
		Transaction t = session.beginTransaction(); // 1. comment1
		Product product = new Product();
		product.setId(1); 
		product.setName(name);
		product.setPrice(price);
		try {
			session.save(product);
			t.commit(); // 2. comment2
		} catch (Exception e) {
			t.rollback();
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		TestMain testMain = new TestMain();
		Session session = testMain.getSession();
		testMain.addProduct(session, "product1", "price1");
		if (session != null && session.isOpen()) {
			session.close();
		}
	}

}

說明:
1. <generator class="assigned" /> 
id 的產生策略是自己指定, 所以在程式碼中有 product.setId(1); 否則無法新增成功
2.  Transaction t = session.beginTransaction();
Hibernate本身沒有實現自己的事務管理功能,而是對底層JDBC事務或JTA事務的輕量級封裝
3.
Hibernate可以配置為JDBCTransaction或者是JTATransaction,這取決於你在hibernate.properties中的配置: 
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory 
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JDBCTransactionFactory
如果你什麼都不配置,預設情況下使用JDBCTransaction
4. 在Hibernate中,Session開啟的時候,就會自動conn.setAutoCommit(false),不像一般的JDBC,預設都是true,所以你最後不寫commit也沒有關係,由於Hibernate已經把AutoCommit給關掉了,所以用Hibernate的時候,你在程式中不寫Transaction的話,資料庫根本就沒有反應。

JDBC和Hibernate 處理事務的關聯


Hibernate本身沒有實現自己的事務管理功能,而是對底層JDBC事務或JTA事務的輕量級封裝

JTA

JTA來管理跨Session的長事務,那麼就需要使用JTATransaction


javax.transaction.UserTransaction tx = new InitialContext();.lookup("javax.transaction.UserTransaction");;


Session s1 = sf.openSession();;
...
s1.flush();;
s1.close();;


...


Session s2 = sf.openSession();;
...
s2.flush();;
s2.close();;


tx.commit();;




Hibernate Transaction是從Session中獲得的,tx = session.beginTransaction(),最後要先提交tx,然後再session.close,這完全符合JDBC的Transaction的操作順序,但是這個順序是和JTA的Transactioin操作順序徹底矛盾的!!! JTA是先啟動Transaction,然後啟動Session,關閉Session,最後提交Transaction,因此當你使用JTA的Transaction的時候,那麼就千萬不要使用Hibernate的Transaction,而是應該像我上面的JTA的程式碼片斷那樣使用才行。 

相關推薦

Java事務管理Hibernate

環境與版本Hibernate 版本:Hibernate 4.2.2 (下載後的檔名為hibernate-release-4.2.2.Final.zip,解壓目錄hibernate-release-4.2.2.Final)資料庫: oracle 10g匯入lib\require

Java-事務管理

pri getc 自己 forname rollback ger [] string 將不 1、事務的概念:   事務指邏輯上的一組操作,組成這組操作的各個單元,要麽全部成功,要麽全部不成功。 2、 管理事務:   2.1. 數據庫默認的事務    數據庫默認支持事務的,但

Java記憶體管理類似-Xms、-Xmx 這些引數的含義

Java記憶體管理之類似-Xms、-Xmx 這些引數的含義 答: 1.堆記憶體分配: JVM 初始分配的記憶體由**-Xms** 指定,預設是實體記憶體的 1/64; JVM 最大分配的記憶體由**-Xmx** 指定,預設是實體記憶體的 1/4; 預設空餘

Java記憶體管理JVM 記憶體劃分

JVM 記憶體劃分 方法區(執行緒共享):常量、靜態變數、JIT(即時編譯器) 編譯後的程式碼也都在方法區; 堆記憶體(執行緒共享):垃圾回收的主要場所; 程式計數器: 當前執行緒執行的位元組碼的位置指示器; 虛擬機器棧(棧記憶體):儲存區域性變數、基本資料

Java記憶體管理GC垃圾回收機制是什麼?什麼是垃圾?如何判斷是否為垃圾?

文章目錄 1. 垃圾回收機制是什麼? 2. 什麼是垃圾呢?如何判斷是否為垃圾呢? 3. GC root指的是誰? 1. 垃圾回收機制是什麼? 垃圾回收機制讓開發者無需關注空間的建立和釋放,而是以守護程序的形式在後臺自動回收垃圾

Java記憶體管理記憶體洩露是什麼?什麼情況下會導致記憶體洩露?

文章目錄 1. 靜態類的使用 2. 資源連線的使用 3. 監聽器的使用 雖然Java擁有垃圾回收機制,但同樣會出現記憶體洩露問題,我們說一下比較主要的三種情況。 1. 靜態類的使用 諸如 HashMap、Vector 等集

Java記憶體管理Java堆結構是怎麼樣的?裡面有什麼東西?

文章目錄 1. 剛剛建立的物件 2. 存活了一段時間的物件 3. 永久存在的物件 一塊 Java 堆空間一般分成三部分,這三部分用來儲存三類資料:新生代、老年代、永久代。 1. 剛剛建立的物件 在程式碼執行時會持續不斷地創

Java記憶體管理用什麼方式回收垃圾、管理記憶體呢?垃圾回收演算法有哪些?

文章目錄 1. 什麼是垃圾? 2. 標記-清理(Marked-Sweep) 3. 標記-整理(Marked-Compact) 4. 複製(Copying) 6. Java分代回收機制 6.1 新生代-複製 回收機制

Spring框架的事務管理程式設計式的事務管理(瞭解)

1. 說明:Spring為了簡化事務管理的程式碼:提供了模板類 TransactionTemplate,所以手動程式設計的方式來管理事務,只需要使用該模板類即可! 2. 手動程式設計方式的具體步驟如下: 1. 步驟一:配置一個事務管理器,Spring使用PlatformT

Java記憶體管理類似-Xms、-Xm 這些引數的含義

Java記憶體管理之類似-Xms、-Xmx 這些引數的含義 答: 1.堆記憶體分配: JVM 初始分配的記憶體由**-Xms** 指定,預設是實體記憶體的 1/64; JVM 最大分配的記憶體由**-

Spring框架的事務管理基於AspectJ的XML方式(重點掌握)

1. 步驟一:恢復轉賬開發環境(轉賬開發環境見“https://www.cnblogs.com/wyhluckdog/p/10137283.html”) 2.步驟二:引入AOP的開發包3.步驟三:引入applicationContext.xml配置檔案  * 配置檔案的基本配置為: <?xml

Spring框架的事務管理基於AspectJ的註解方式(重點掌握,最簡單的方式)

1. 步驟一:恢復轉賬的開發環境(具體開發環境實現見:https://www.cnblogs.com/wyhluckdog/p/10137283.html)2. 步驟二:applicationContext的基本配置為: <?xml version="1.0" encoding="UTF-8"?

Spring事務管理AOP方法

使用AOP完成Spring事務管理 <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <

Spring事務管理幾種方式實現事務

1、事務認識 大家所瞭解的事務Transaction,它是一些列嚴密操作動作,要麼都操作完成,要麼都回滾撤銷。Spring事務管理基於底層資料庫本身的事務處理機制。資料庫事務的基礎,是掌握Spring事務管理的基礎。這篇總結下Spring事務。 事務具備ACID四種特性,

spring事務管理四:宣告式事務管理:使用事務註解的方式

事務註解的方式,相對xml的方式來說,有優點,無需配置需要事務的業務方法的切點和事務屬性。但是也有缺點,就是需要在每個需要事務的業務方法上加上一個註解@Transaction,否則事務不會生效。 這裡沿用之前spring事務管理的程式碼: pom.xml依賴部分: <depen

spring事務管理三:宣告式事務管理:使用xml配置檔案的方式

這種方式是開發中常見的一種方式:利用aop的思想,將需要事務管理的業務方法通過xml配置的方式,將事務管理加在該類的相關方法上。這種方法的優點是,一次xml配置,後期不用關心業務類增加或者減少,通過xml中配置的匹配資訊,會去找業務類所在的包和方法,然後加上事務。 重點是配置<tx:a

spring事務管理二:宣告式事務管理:使用代理方式

spring宣告式事務管理,分為三種方式,分別是: 1、使用代理類TransactionProxyFactoryBean的方式 2、使用aspectj+xml配置的方式 3、使用事務註解的方式 其中後面兩種是比較常用的,使用xml和註解的方式。 這裡介紹使用代理類Transa

Spring事務管理程式設計式事務場景及使用詳解

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-

java事務管理

一、事務概念 事務,通俗講就是一組操作資料庫的動作集合。事務(Transaction):是併發控制的單元,是使用者定義的一個操作序列。這些操作要麼都做,要麼都不做,是一個不可分割的工作單位。通過事務,sql server 能將邏輯相關的一組操作繫結在一起,以便

Java三大框架——Hibernate中的三種資料持久狀態和快取機制

Hibernate中的三種狀態     瞬時狀態:剛建立的物件還沒有被Session持久化、快取中不存在這個物件的資料並且資料庫中沒有這個物件對應的資料為瞬時狀態這個時候是沒有OID。   持久狀態:物件經過Session持久化操作,快取中存在這個物件的資料為持久狀