Spring+hibernate+mysql事物不回滾的原因以及處理
最近專案突然出了點問題,然後發現用Service層下面的一個類的一個方法裡的事務居然沒有回滾。然後自己寫了一個測試方法經過了N次測試都是不回滾。以下是測試方法的一部分:
@Transactional(propagation =Propagation.REQUIRED,rollbackFor=RuntimeException.class)
public String getOnLineNum(String securecrt){
History his=new History();
his.setItem("123");
//此處特意設定一個超出欄位長度使其出錯
Ludan lu=new Ludan();
lu.setRoomName("33333333333333333");
historyDao.save(his);
ludanDao.save(lu);
return "123";
}
以上程式碼經過許多次的測試都是會把history表存入記錄,但是ludan報錯存入不了,這樣相當於事務並沒有回滾。
如下是spring的部分配置:
<!-- spring 事務管理 start-->
<bean id="transactionManager"
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
<!-- 宣告使用註解式事務 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
一。 如上就是問題,然後經過大範圍的查閱以及搜尋,最後總結了幾點Spring事務不回滾的原因:
1.你自己捕獲異常了,沒有丟擲去讓Spring知道。
2.沒有正確配置Spring中的事務。
3.Service層次問題,即一些邏輯問題。
4.MySQL不支援事務。
二。解決辦法
這裡重點講解一下上線的第四種原因的解決辦法,這也是本人專案中遇到的問題。即MYSQL預設的資料庫模式是MyISAM,而這個模式是不支援事務的,並且在安裝mysql的時候預設的資料庫模式就是MyISAM。在mysql裡輸入:show engines;就會看到如下的畫面:
可以看到只有InnoDB才支援事務。因此要實現mysql的事務必須先把mysql資料庫模式轉換成InnoDB。
具體方法如下:
1.開啟根目錄下得my.ini檔案,在[mysqld]下加入:
default-storage-engine=INNODB
如果有skip-innodb,那就把這行注掉即可。
2.重啟mysql服務
3.再次進入mysql,輸入:show engines;就可以看到預設的資料庫模式已經是INNODB了;
4.原來存在的表則需要刪除以後再重新建一個就是INNODB的了,如果不想刪除,那就進入mysql,更新一下表引擎就可以了
執行:alter table 表名 ENGINE=InnoDB;
然後在執行:show table status from 資料庫名 where name='表名';就可以檢視狀態了
5.再次測試上面的程式碼就發現事務回滾了。
三。總結
對於這個自己遇到的問題可能是大部分人都遇到過的問題吧,也算是自己的經驗不足造成的,因此記錄下來方便一些像我一樣走在程式的路上的朋友們,希望能對大家有一些幫助,也同時做一個自己的工作記錄吧,以後也可以回來再次審查。
轉載於:https://my.oschina.net/airship/blog/832516