1. 程式人生 > >hibernate中事務管理

hibernate中事務管理

1、

(1)Hibernate可以理解為一箇中間件。它負責把java程式的SQL語句接收過來併發送到資料庫,而資料庫返回的資訊由Hibernate接收後直接生成一個物件傳給java.

在Hibernate中有兩個特有的檔案,一個是以.hbm.xml結尾的對映檔案,一個是以.cfg.xml結尾的配置檔案。.cfg.xml檔案的作用是連線資料庫,檔案內部其實就是一個由user,password,url,driver組成的連結庫的基本資訊。.hbm.xml檔案是對資料庫中表的對映檔案。

(2)Hibernate工作原理

①讀取並解析hibernate.cfg.xml配置檔案;

②由hibernate.cfg.xml中的<mapping resource="com/xx/user.hbm.xml">讀取並解析對映資訊;

③.通過SessionFactory sf = config.buildSessionFactory();建立SessionFactory

④Session session = sf.openSession();//開啟Sesssion

⑤Transaction tx = session.beginTransaction();//建立並啟動事務Transation

⑥persistent operate操作資料,持久化操作

⑦tx.commit();//提交事務

⑧關閉Session

⑨關閉SesstionFactory

(3)使用Hibernate的原因如下:

① 對JDBC訪問資料庫的程式碼做了封裝,大大簡化了資料訪問層繁瑣的重複性程式碼。

②HIbernate是基於JDBC的主流持久化框架,是一個優秀的物件關係對映實現,它在很大程度上簡化了DAO層的編碼工作;

③Hibernate使用java反射機制,而不是位元組碼增強程式來實現透明性;

④Hibernate效能非常好,因為它是一個輕量級框架,對映的靈活性很出色,它支援各種關係資料庫,從一對一到多對多的各種複雜關係。


2、在談Spring事務管理之前我們想一下在我們不用Spring的時候,在Hibernate中我們是怎麼進行資料操作的。在Hibernate中 我們每次進行一個操作的的時候我們都是要先開啟事務,然後進行資料操作,然後提交事務,關閉事務,我們這樣做的原因是因為Hibernate預設的事務自 動提交是false,他是需要我們人為的手動提交事務,假如你不想每次都手動提交事務的話,你可以在hibernate.cfg.xml我檔案中把它設定 為事務自動提交:

<property name="hibernate.connection.autocommit">true</property> 

當我們Spring對我們的Hibernate進行整合之後,我們的程式碼又出現了什麼變化呢?整合,之後,我們不再是每次都去拿 Session進行資料操作了,也不需要每次都開啟事務,提交事務了,我們只需要Spring給我們提供的一個HibernateTemplate,我們 直接用這個類裡面給我們提供的資料操作方法就可以操作資料了。我們在也看不到關於事務的程式碼了,那Spring究竟有沒有在他的操作方法裡面封裝事務處理 呢?有的人直接HibernateTemplate裡面提供的方法操作資料,成功了,有的人卻又失敗了,這到底是怎麼回事呢?其實這裡要看我們是怎樣整合 我們的Hibernate和Spring,如果在整合的過程中,我們拋棄了hibernate.cfg.xml檔案,直接在Spring的的配置檔案中進 行配置資料來源的話,那你直接用HibernateTemplate裡面提供的方法是可以成功操作資料的,如果你還是用hibernate.cfg.xml 來配置資料來源,在Spring的配置檔案中引用hibernate.cfg.xml檔案,那麼你不能成功,這其中的原因就是因為如果你用 hibernate.cfg.xml檔案配置資料來源,就像我們前面說的,Hibernate預設是手動提交事務,而HibernateTemplatel 提供的方法裡面並沒有提供事務提交,而如果你用Spring的配置檔案來配置資料來源,Sping預設是自動提交的,所以就會成功,如果你想把Spring 設定為手動提交你可以在起配置檔案中進行配置:

<property name="defaultAutoCommit">
    <value>false</value>
</property> 

縱然我們把它的事務提交方式設定為自動,它可以進行資料操作,但是這樣並不滿足我們實際的業務需求,因為有時候在我儲存一個數據之後,我希望他能繼 續儲存另一條資料,我希望在儲存完兩條或者多條之後一起進行事務提交,這樣即使出錯,我們可以回滾,取保資料的一致性,要麼都成功要麼都失敗,這時候我們 就不能每儲存完一條資料之後事務就自動提交,因為這樣它們不在同一個事務當中,我們不能保證資料的一致行。所以這時候我們就需要手動的來配置我們的事務, 這就需要用到Spring為Hibernate提供的事務管理機制,Spring提供的事務管理可以分為兩類:程式設計式的和宣告式的,程式設計式,其實就是在代 碼裡面來控制,像Hibernate操作資料一樣,開啟事務,提交事務,這種方式有一定的侷限性,所以我們一般是用宣告式來配置我們的事務。

宣告式事務配置主要分以下幾步:

1、宣告式事務配置

  • 配置事務管理器;
  • 事務的傳播特性;
  • 那些類那些方法使用事務。 複製程式碼 複製程式碼
    <!-- 配置事務管理器 指定其作用的sessionFactory把事務交給Spring去處理 -->
    
        <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory">
        <ref bean="sessionFactory"/>
        </property>
        </bean>
    
    <!-- 配置事務的傳播特性 -->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
        <tx:method name="save*" propagation="REQUIRED"/>
        <tx:method name="delete*" propagation="REQUIRED"/>
        <tx:method name="update*" propagation="REQUIRED"/>
        <tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED"/>
        <tx:method name="*" read-only="true"/>
        </tx:attributes>
        </tx:advice>
    
    <!-- 那些類的哪些方法參與事務 -->
        <aop:config>
        <aop:pointcut id="allServiceMethod" expression="execution(* com.coe.service.*.*(..))"/>
        <aop:advisor pointcut-ref="allServiceMethod" advice-ref="txAdvice"/>
        </aop:config> 
    複製程式碼 複製程式碼

    我們在配置事務的時候,我們一般是把事務邊界設定到service層,也就是你的業務邏輯層,因為我們很多時候都是在我們的業務邏輯層來完成我們一 些列的資料操作,如果放到Dao資料層,其粒度太小了。另外,如果我們把事務配置在業務邏輯層的話,對我們的二級快取也是有好處的,這個大家以後實際操作 的時候會發現。

    2、編寫業務邏輯方法

    這時候我們就可以在我們業務邏輯層用HibernateTemplate裡面提供的資料操作方法來編寫我們的業務邏輯方法了,當然我們的方法必須要 是以我們事務配置裡面配置的一樣,用save,delete,update,get做我們的方法的開頭。需要注意的是,預設情況下執行期異常才會回滾(包 括繼承了RuntimeException子類),普通異常是不會滾的。

    最後我們順便總結一下事務的幾種傳播特性:

    1. PROPAGATION_REQUIRED: 如果存在一個事務,則支援當前事務。如果沒有事務則開啟;

    2. PROPAGATION_SUPPORTS: 如果存在一個事務,支援當前事務。如果沒有事務,則非事務的執行;

    3. PROPAGATION_MANDATORY: 如果已經存在一個事務,支援當前事務。如果沒有一個活動的事務,則丟擲異常;

    4. PROPAGATION_REQUIRES_NEW: 總是開啟一個新的事務。如果一個事務已經存在,則將這個存在的事務掛起;

    5. PROPAGATION_NOT_SUPPORTED: 總是非事務地執行,並掛起任何存在的事務;

    6. PROPAGATION_NEVER: 總是非事務地執行,如果存在一個活動事務,則丟擲異常;

    7. PROPAGATION_NESTED:如果一個活動的事務存在,則執行在一個巢狀的事務中. 如果沒有活動事務, 則按TransactionDefinition.PROPAGATION_REQUIRED 屬性執行。