1. 程式人生 > >spring事務和myBatis事務的設定

spring事務和myBatis事務的設定

spring和myBatis的事務是怎麼設定的

Spring配置檔案中關於事務配置總是由三個組成部分,分別是DataSource、TransactionManager和代理機制這三部分,


無論哪種配置方式,一般變化的只是代理機制這部分。DataSource、TransactionManager這兩部分只是會根據資料訪問


方式有所變化,比如使用myBatis進行資料訪問時,DataSource實際為org.apache.commons.dbcp.BasicDataSource,TransactionManager的實現為


org.springframework.jdbc.datasource.DataSourceTransactionManager。

spring事務的設定

spring.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: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-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
	
	<!-- 
		 isolation 表示事務的隔離級別
                DEFAULT 是獲取資料庫的隔離界別
                READ_UNCOMMITTED 讀取到其他spring方法未提交的資料 引發髒讀問題
                READ_COMMITTED 只能讀取到其他事務已經提交的資料  預設
                REPEATABLE_READ 可重複讀  解決髒讀不可重複讀  引發幻讀
	            SERIALIZABLE    序列化 解決了所有問題
	            隔離級別越高 需要消耗更多的資源去處理 效率低下
	            
	     propagation 傳播特性 方法和方法之間的呼叫  事務是否能夠傳播
				- REQUIRED (spring 預設的傳播特性)
				   必須存在一個事務 如果沒有事務 建立一個事務  如果父方法存在事務使用父方法的事務
				- REQUIRES_NEW   
				 必須存在一個事務 不管有沒有事務都要自己建立一個事務  
				- SUPPORTS
				不會建立事務 如果有事務在事務中執行 沒有事務 不使用事務
				- MANDATORY(必須存在事務)
				不會建立事務 有事務 使用當前事務  沒有事務跑出 錯誤狀態異常
				- NEVER (不能存在事務)
				不會建立事務 沒有事務正常執行 有事務丟擲異常 
				- NOT_SUPPORTED
				不支援事務 如果存在事務就掛起 沒有事務正常執行
				- NESTED (少用)
				巢狀異常 不同的資料來源之間的事務處理   相同的資料 就是 REQUIRED
				
			spring tx事務處理中 只有執行時異常才會自動回滾資料	
			  rollback-for 指定需要回滾的非執行時異常
			  no-rollback-for="" 指定不需要回滾的執行時異常
			  
			timeout="-1" 會一直等待資料操作完成
			 預設的-1一直等待
			 單位s秒
			  
			read-only="true" 該方法不使用事務  
	 -->
	
	
	<!-- 讀取jdbc.properties檔案 -->
	<context:property-placeholder location="classpath:/jdbc.properties"></context:property-placeholder>
	
	<!-- 資料的連線  資料來源 -->
	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="url" value="${url}"></property>
		<property name="driverClassName" value="${driverClass}"></property>
		<property name="username" value="${account}"></property>
		<property name="password" value="${password}"></property>
	</bean>
	
	<!-- 事務管理器 spring幫助我們控制事務 -->
	<bean id="transManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>

	<!-- 當切點攔截到某個操作的方法  傳送通知給tx定義的通知管理  呼叫事務管理器 提交和回滾 -->
	<tx:advice id="myAdvice" transaction-manager="transManager">
		<tx:attributes>
			<!-- 預設的配置 -->
			<tx:method name="add*" propagation="REQUIRED" />
			<tx:method name="query*" propagation="REQUIRED" />
			<tx:method name="update*" propagation="REQUIRED" />
			<tx:method name="delete*" propagation="REQUIRED" />
			<tx:method name="*" read-only="true" />
		</tx:attributes>
	</tx:advice>

	<!-- aop切面 -->
	<aop:config>
		<aop:pointcut id="myPointCut"
			expression="execution(* cn.*..*.service.EmpService.*(..))" />
		<aop:advisor advice-ref="myAdvice" pointcut-ref="myPointCut" />
	</aop:config>
	
	<!-- 建立jdbcTemplate物件 -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
</beans>

dao層中的自動裝配

	
	//自動裝配
	@Autowired
	private JdbcTemplate jdbcTemplate;


myBatis事務的設定

spring.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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:mvc="http://www.springframework.org/schema/mvc"

	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
		">
	
	
	<!-- springmvc的配置只能掃描控制層  spring配置檔案不能掃描控制層 -->
	<context:component-scan base-package="cn.et">
		<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
	</context:component-scan>
	
	<!-- 讀取jdbc.properties檔案 -->
	<context:property-placeholder 
	location="classpath:/cn/et/mybatis/lesson06/utils/jdbc.properties" />
	
	<!-- 資料庫連線池 -->
	<bean id="dataSource"
		class="org.apache.commons.dbcp.BasicDataSource">
		<property name="url" value="${url}"></property>
		<property name="driverClassName" value="${driverClass}"></property>
		<property name="username" value="${account}"></property>
		<property name="password" value="${password}"></property>
		<!-- 
			initialSize   10
			預設生成10個連線,那麼要用到連線的時候就直接拿一條出來用就可以了,
			就不用等到用的時候再去產生連線
		 -->
		<property name="initialSize" value="10"></property>
		<!-- 發起一條測試的sql語句去連線一下資料庫,看是否可以正常連線資料庫 -->
	</bean>
	
	<!-- 事務管理器 spring幫助我們控制事務 -->
	<bean id="transManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>

	<!-- 需要匯入架包aspectjweaver 事務架包 -->
	<!-- 當切點攔截到某個操作的方法  傳送通知給tx定義的通知管理  呼叫事務管理器 提交和回滾 -->
	<tx:advice id="myAdvice" transaction-manager="transManager">
		<tx:attributes>
			<!-- 預設的配置 -->
			<tx:method name="add*" propagation="REQUIRED" />
			<tx:method name="query*" propagation="REQUIRED" />
			<tx:method name="update*" propagation="REQUIRED" />
			<tx:method name="delete*" propagation="REQUIRED" />
			<!-- *代表了除了上面配置的方法都不使用事務 -->
			<tx:method name="*" read-only="true" />
		</tx:attributes>
	</tx:advice>

	<!-- aop切面 -->
	<aop:config>
		<aop:pointcut id="myPointCut" expression="execution(* cn.*..*.service.EmpService.*(..))" />
		<aop:advisor advice-ref="myAdvice" pointcut-ref="myPointCut" />
	</aop:config>
	
	<!-- 建立一個jdbc模板SqlSessionFactoryBean -->
	<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	
	<!-- 這裡一定要用sqlSessionFactoryBeanName,不然載入不了driverClass -->
	<!-- 掃描介面對映和註解和xml檔案 -->
	<bean id="scanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="sqlSessionFactoryBeanName" value="sessionFactory"></property>
		<!-- 
			如果對映的是Mapper介面直接放到mapper包裡面掃描就發好了
			如果對映的是xml配置檔案需要把配置檔名改成對應的介面一樣的名稱,並都要放到mapper包下
		 -->
		<property name="basePackage" value="cn.*..*.mapper"></property>
	</bean>
	
</beans>



dao層或service層的自動裝載

	@Autowired
	private EmpMapper mapper;

這裡的裝配可以是dao層,也可以是service層,因為mapper層映射了需要實現的所有sql語句,還可以實現動態的sql語句,

所以mapper可以完全替代dao層。那麼這裡就可以直接裝配到service層也是一樣的。