SpringMVC+MyBatis配置宣告式事務的問題
阿新 • • 發佈:2019-02-03
網路上關於Spring宣告式事務的部落格一堆一堆地,原本不用自己再記筆記,但我最近在用SpringMVC+MyBatis時遇到了事務問題;深知自己水平不高,忘東西又快,因此一解決問題還是第一時間記下來,以備後用。
我的環境是Spring、SpringMVC、MyBatis3、MariaDB和Tomcat
我遇到的問題是事務不起作用,雖然多次資料庫操作中有異常出現,但還是部分提交,並沒有回滾;
我的配置是這樣的:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/> <tx:method name="insert*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" /> <tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" /> <tx:method name="save*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" /> <tx:method name="*" propagation="REQUIRED" read-only="true"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="pc" expression="execution(* com.xss.*.*.service.impl.*.*(..))" /> <aop:advisor pointcut-ref="pc" advice-ref="txAdvice" /> </aop:config>
這段配置應該是沒有問題的,於是我就想會不會是MariaDB的儲存引擎不支援事務,於是從網上找到了這麼一段話:
MariaDB預設的儲存引擎是Maria,不是MyISAM。Maria可以支援事務,但是預設情況下沒有開啟事務支援,因為事務支援對效能會有影響。 可以通過以下語句,轉換為支援事務的Maria引擎:
ALTER TABLE ‘tablename’ ENGINE=MARIA TRANSACTIONAL=1;
但我按照上面所述修改了資料庫的儲存引擎,事務仍然不起作用。
注:在MariaDB(MySQL)資料中,InnoDB和BerkeleyDB兩種儲存引擎是支援事務的,MariaDB引進的新引擎Aria預設不支援事務,可以通過上面的程式碼修改。
糾結了許久終於發現還是自己的配置出了問題,但並非是事務配置有問題,而是Spring元件掃描配置出了問題。
由於採用的是SpringMVC、 MyBatis,故統一採用了@Service、@Controller註解來宣告Service和Controller 元件,於是我在Spring和SpringMVC的配置檔案均用一行程式碼配置了Spring的元件自動掃描:
<context:component-scan base-package="com.xss.crm" />
而由於伺服器啟動時的載入Spring相關配置檔案的順序為applicationContext.xml(Spring的配置檔案) ---> applicationContext-mvc.xml(SpringMVC的配置檔案),按照上面的配置Spring載入applicationContext.xml配置檔案時會載入@Controller註解標註的Controller元件,並且對其進行掃描裝配,但是此時的Service還沒有進行事務增強處理,得到的將是原樣的Service(沒有經過事務加強處理,故而沒有事務處理能力),所以我們應用在applicationContext.xml(Spring配置檔案)中不掃描Controller,而在applicationContext-mvc.xml(SpringMVC配置檔案)中不掃描Service。
於是Spring和SpringMVC配置應該像下面的這樣:
applicationContext.xml(Spring配置檔案)
<!-- 自動掃描元件,這裡不掃描 controller,它們是在ApplicationContext-mvc.xml中配置掃描的,如果不去除會影響事務管理 -->
<context:component-scan base-package="com.xss.crm">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
applicationContext-mvc.xml(SpringMVC配置檔案)
<!-- 掃描所有的controller 但是不掃描service-->
<context:component-scan base-package="com.xss.crm">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
修改配置後再測試,事務成功回滾。