Spring的事務管理(二)宣告式事務管理

z1340954953發表於2018-07-18

 

Spring支援宣告式和程式設計式兩種配置事務的方式

程式設計式事務管理使用TransactionTemplate或者直接使用底層的PlatformTransactionManager。對於程式設計式事務管理,spring推薦使用TransactionTemplate。

宣告式事務是利用Spring的AOP在方法的前後進行攔截,在呼叫方法前加入一個事務,方法執行完成後根據執行情況回滾或者提交。宣告式事務的最大特點,就是不侵入程式碼,只需在配置檔案中配置或者使用@Transactional註解定義事務規則,應用到方法上

宣告式事務管理使業務程式碼不受汙染,一個普通的POJO物件,只要加上註解就可以獲得完全的事務支援。
和程式設計式事務相比,宣告式事務唯一不足地方是,後者的最細粒度只能作用到方法級別,無法做到像程式設計式事務那樣可以作用到程式碼塊級別。
但是即便有這樣的需求,也存在很多變通的方法,比如,可以將需要進行事務管理的程式碼塊獨立為方法等等。

宣告式事務管理也有兩種常用的方式,一種是基於tx和aop名字空間的xml配置檔案,另一種就是基於@Transactional註解。顯然基於註解的方式更簡單易用,更清爽。

基於註解@Transactional的宣告式事務配置

以整合mybatis為例

xml標頭檔案資訊,加入tx名稱空間

<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.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 class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	<property name="basePackage" value="cn.bing.mapper"></property>
	<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
	<property name="annotationClass" value="org.springframework.stereotype.Repository"></property>
</bean>
<!-- 配置事務 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 開啟事務配置的註解支援 -->
<tx:annotation-driven transaction-manager="transactionManager"/>

  MyBatis自動參與到spring事務管理中,無需額外配置,  只要org.mybatis.spring.SqlSessionFactoryBean引用的資料來源與DataSourceTransactionManager引用的資料來源一致即可,否則事務管理會不起作用。

最後在service方法上加上@Transactional配置事務,啟用就行了,下面簡單測試下.

建立StudentServiceImpl類

public interface StudentService {
	public Student queryStudentInfo(Integer id);
	public void addStudentInfo(Student stu);
}
@Service("studentService")
public class StudentServiceImpl implements StudentService {
	@Autowired
	private StudentMapper mapper;
	@Transactional
	@Override
	public Student queryStudentInfo(Integer id) {
		 return mapper.queryStudentInfo(id);
	}
	@Transactional
	@Override
	public void addStudentInfo(Student stu) throws NullPointerException {
		mapper.insertStudent(stu);
		throw new NullPointerException();
	}
}

能掃描到這個service類加上掃包配置

<!-- 註解支援 -->
<context:annotation-config></context:annotation-config>
<!-- 掃描包,自動建立bean -->
<context:component-scan base-package="cn.bing" use-default-filters="false">
	<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>

Junit測試下,能列印學生資訊,ok

@RunWith(value=SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:springContext.xml")
public class SpringTest {
	@Autowired
	@Qualifier("studentService")
	private StudentService studentService;
	@Test
	public void test(){
		Student stu = studentService.queryStudentInfo(1);
		System.out.println(stu);
	}
}

@Transactional註解的說明

屬性 型別 說明
value String 指定使用的事務管理器
propagation 列舉型別 指定事物的傳播行為
isolation 列舉型別 指定事務的隔離級別
readonly boolean

讀寫或者只讀事務,預設是讀寫,

配置為只讀事務,會優化

timeout int 指定超時時間
rollbackFor Class物件陣列,必須繼承自Throwable 導致事務回滾的異常類陣列
rollbackForClassName 類名陣列,必須繼承自Throwable 導致事務回滾的異常類名字陣列
noRollbackFor Class物件陣列,必須繼承自Throwable 不會導致事務回滾的異常類陣列
noRollbackForClassName 類名陣列,必須繼承自Throwable 不會導致事務回滾的異常類名字陣列

xml配置宣告式事務

在xml配置切面,將事務織入到業務方法中

<!-- 配置事務 -->
	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<tx:advice id="advice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="query*" propagation="REQUIRED" read-only="true" />
			<tx:method name="update*" propagation="REQUIRED" read-only="false"
				rollback-for="java.lang.Exception" />
			<tx:method name="add*" propagation="REQUIRED" read-only="false" />
		</tx:attributes>
	</tx:advice>
	<aop:config>
		<aop:pointcut id="studentServicePointCut" expression="execution (** cn.bing.service..*(..))" />
		<aop:advisor advice-ref="advice" pointcut-ref="studentServicePointCut" />
	</aop:config>

參考:https://blog.csdn.net/bao19901210/article/details/41724355

相關文章