歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Spring+Hibernaet+MySQL事務處理中遇到問題及解決

spring的事務處理本來就是依賴於底層的實現,比如hibernate及數據庫本身。所以,當使用mysql數據庫時,首先要確定的是,所操作的對象表是innodb格式的。

1. read-only方法中進行更新或插入操作時,並不總報錯

在service層的方法中定義了事務,並且在spring配置文件中定義了如下的傳播方式:

<tx:attributes >

  <tx:method name="save*" propagation="REQUIRED" />

  <tx:method name="update*" propagation="REQUIRED" />

  <tx:method name="*" read-only= "true" />

 </tx:attributes>

假設有一個實體名稱為User,則如果在在service的一個方法中想保存或更新它,而這個方法又忘記了以save或update開頭,就會導致一些莫名其妙的事情發生,有時會報錯(這可以理解),但有時又不會報錯,動作卻沒有執行,反復觀察,發現以下規律:

當更新user的操作時,即此時user的主鍵不為null時,調用Dao中的Hibernate的saveOrUpdate方法時,程序不報錯,但修改動作未起作用;

當進行插入操作時,此時user的主鍵為Null(庫中的主鍵采用自增),此時調用saveOrUpdate方法時,程序報錯:Connection is read-only. Queries leading to data modification are not allowed.

2. 在事務方法中拋出異常,並不總回滾

一個事務方法中:

xxxDao.save(user); 

..... 

throw new Exception("要求回滾"); 

拋出異常後,期望事務能回滾,觀察數據庫,卻發現改變已寫進持久層了。

原因是這樣的:Spring、EJB的聲明式事務默認情況下都是在拋出unchecked exception後才會觸發事務的回滾。Exception這個異常是checked異常,所以無法觸發回滾事件,如果換成拋出RuntimeException異常,則程序運行就符合預期了。

3. 事務方法嵌套調用

在一個service中,用一個read-only方法調用非read-only方法,則發現整個調用都read-only了。

這是因為:service內部方法間調用,被調用方法設定的事務行為將會失效,事務行為由最外層方法設置的事務行為控制。

4. 事務回滾未提交,並不表示對底層數據庫沒有任何影響。

下面的代碼:

xxxDao.save(user);
Integer userId = user.getId();
.....
throw new RuntimeException("要求回滾");

事務會成功回滾,數據表中也未插入新的記錄。但觀察發現,userId的值也取到了,比如說userId=9800,如果再向數據庫增加一條記錄,則自增的id值會變成9801!

也就是說,雖然由於事務回滾沒有向持久層插入記錄,但數據表的自增字段的值已經被改變了。(這一塊的機制細節沒功夫研究了,有人了解的話,告訴我一下)

Hibernate3.1.2_中文文檔PDF  http://www.linuxidc.com/Linux/2016-02/128462.htm

Hibernate學習入門教程  http://www.linuxidc.com/Linux/2015-08/121498.htm

在Hibernate中開啟日志 http://www.linuxidc.com/Linux/2015-07/120499.htm

Hibernate+JUnit測試實體類生成數據庫表  http://www.linuxidc.com/Linux/2015-07/120161.htm

Hibernate整體理解 http://www.linuxidc.com/Linux/2014-07/104405.htm

Hibernate的映射機制  http://www.linuxidc.com/Linux/2014-12/110265.htm

Hibernate 的詳細介紹:請點這裡
Hibernate 的下載地址:請點這裡

Copyright © Linux教程網 All Rights Reserved