Spring事務

在spring框架中使用事務處理是比較方便的,spring提供了兩個方式,一個基於xml配置,另外一個使用註解。

基於XML配置支持事務特性:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:context="http://www.springframework.org/schema/context"
     xmlns:p="http://www.springframework.org/schema/p"
     xmlns:aop="http://www.springframework.org/schema/aop"
     xmlns:tx="http://www.springframework.org/schema/tx"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context.xsd
         http://www.springframework.org/schema/aop 
         http://www.springframework.org/schema/aop/spring-aop.xsd
         http://www.springframework.org/schema/tx
     	 http://www.springframework.org/schema/tx/spring-tx.xsd">
	
    
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/test"></property>
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
		<property name="user" value="root"></property>
		<property name="password" value="677714"></property>
		<property name="initialPoolSize" value="3"></property>
		<property name="maxPoolSize" value="10"></property>
	</bean>
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<bean id="UserDao" name="UserDao" class="yzr.dao.UserDao" >
		<property name="jdbcTemplate" ref="jdbcTemplate"></property>
	</bean>
	<bean name="UserService" class="yzr.service.UserService" >
		<property name="userDao" ref="UserDao"></property>
	</bean>
	<bean name="UserAction" class="yzr.action.UserAction" >
		<property name="userService" ref="UserService"></property>
	</bean>
	

	<bean id="txManaer"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<tx:advice id="txAdvice" transaction-manager="txManaer">
		<tx:attributes>
			<tx:method name="*" read-only="false" />
		</tx:attributes>
	</tx:advice>
	<aop:config>
		<aop:pointcut expression="execution(* yzr.service.*Service.*(..))"
			id="pt" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="pt" />
	</aop:config>
</beans>     

 1.需要導入事務和aop的名稱空間。

  2.指定一個事務管理(DataSourceTransactionManager),在上面例子中是spring對jdbc事務管理,使用<tx:advice>節點中的<tx:atrributes>配置事務特性。

  3.綁定事務到攔截的方法上。

爲了測試事務是否回滾,在service中拋出一個異常:

測試1:直接拋出異常

package yzr.service;
import yzr.dao.UserDao;

public class UserService {
	public UserDao userDao;
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}
	public void save(){
		userDao.Add();
		int i=1/0;
	}
}

測試結果:執行報錯,並且數據庫中沒有插入數據

結論:事務回滾了

測試2:try catch異常

package yzr.service;
import yzr.dao.UserDao;

public class UserService {
	public UserDao userDao;
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}
	public void save(){
		try {
			userDao.Add();
			int i = 1 / 0;
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
}

測試結果:執行沒有報錯,數據庫插入了數據。

測試結論:當異常被trycatch之後將屬於正常執行,既不會報錯,也不會事務回滾。


基於使用註解的方式:

在xml中開啓註解掃描,並且開啓事務註解:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:context="http://www.springframework.org/schema/context"
     xmlns:p="http://www.springframework.org/schema/p"
     xmlns:aop="http://www.springframework.org/schema/aop"
     xmlns:tx="http://www.springframework.org/schema/tx"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context.xsd
         http://www.springframework.org/schema/aop 
         http://www.springframework.org/schema/aop/spring-aop.xsd
         http://www.springframework.org/schema/tx
     	 http://www.springframework.org/schema/tx/spring-tx.xsd">

	<!-- 開啓註解 -->
	<context:component-scan base-package="yzr"></context:component-scan>
	
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="jdbcUrl" value="jdbc:mysql://123.207.89.46:3306/test"></property>
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
		<property name="user" value="root"></property>
		<property name="password" value="677714"></property>
		<property name="initialPoolSize" value="3"></property>
		<property name="maxPoolSize" value="10"></property>
	</bean>
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<bean id="UserDao" name="UserDao" class="yzr.dao.UserDao" >
		<property name="jdbcTemplate" ref="jdbcTemplate"></property>
	</bean>
	<bean name="UserService" class="yzr.service.UserService" >
		<property name="userDao" ref="UserDao"></property>
	</bean>
	<bean name="UserAction" class="yzr.action.UserAction" >
		<property name="userService" ref="UserService"></property>
	</bean>
	
	
	
	<!-- 5. 事務控制配置, 基於註解 -->
	
	<!-- 5.1 配置事務管理器類-->
	<bean id="txManaer" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 5.2 開啓事務註解開關 -->
	<tx:annotation-driven transaction-manager="txManaer"/>
	
</beans>

在service中使用@Transactional 


	@Transactional(
			isolation=Isolation.DEFAULT,
			propagation=Propagation.REQUIRED,
			readOnly=false,
			timeout=-1
	)
	public void save(){
		
		deptDao.save();
		//throw new RuntimeException("怎麼還不回滾");
		int i = 1/0;
	}


  數據庫一般都支持事務,像sqlserver,oracle和mysql,但要注意一下的是,當你發現按照上面的配置進行測試事務是否正常回滾的時候,發現事務怎樣都沒有回滾,這時候需要留意一下數據庫引擎是否支持事務特性,打個比如,當你使用的是mysql的時候,輸入show ENGINES;

默認的數據庫引擎是MyIASM引擎,(上圖你看到的默認的是InnoDB是因爲我已經把數據庫改成默認爲InnoDB引擎了),MyIASM引擎是不支持事務的,而且一眼掃過就只有InnoDB支持事務特性。

當你是因爲數據庫引擎問題引起不能正常回滾時,只需要把你mysql的my.ini配置文件將默認引擎改爲InnoDB。然後再使用alter table tableName ENGINE=InnoDB命令

修改mysql的my.ini配置:

default-storage-engine=引擎名稱

然後註釋skip innoDB這一行。

重新啓動mysql服務即可。





發佈了55 篇原創文章 · 獲贊 64 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章