使用@Transactional註解完成事務控制,此註解可新增到類上,則對類中所有方法執行事務的設定,註解新增到方法上,則對該方法執行事務處理
@Transactional(...)註解引數說明:
注意:當一個類中有較多方法時,對方法進行一對一的註解式事務管理太多繁瑣,簡單演示事務特性時可以使用註解式事務,在實際專案中不常用
在組態檔中新增一次,整個專案遵循該事務的設定,是Spring常用的,也是非常有名的事務處理方式
要求專案中的方法命名有規範,例如:
新增操作包含:add,save,insert,set等
更新操作包含:update,change,modify等
刪除操作包含:delete,drop,remove,clear等
查詢操作包含:select,find,search,get等
設定事務切面時,可以使用萬用字元來匹配滿足通配條件的方法
<!-- 此組態檔和applicationContext_service.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/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 匯入applicationContext_mapper.xml -->
<import resource="applicationContext_mapper.xml"/>
<!-- 新增包掃描 -->
<context:component-scan base-package="com.example.service.impl"/>
<!-- 新增事務管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 設定事務切面 -->
<tx:advice id="myadvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*select*" read-only="true"/>
<tx:method name="*search*" read-only="true"/>
<tx:method name="*find*" read-only="true"/>
<tx:method name="*get*" read-only="true"/>
<tx:method name="*update*" propagation="REQUIRED"/>
<tx:method name="*save*" propagation="REQUIRED"/>
<tx:method name="*modify*" propagation="REQUIRED"/>
<tx:method name="*set*" propagation="REQUIRED"/>
<tx:method name="*insert*" propagation="REQUIRED"/>
<tx:method name="*delete*" propagation="REQUIRED"/>
<tx:method name="*remove*" propagation="REQUIRED"/>
<tx:method name="*clear*" propagation="REQUIRED"/>
<tx:method name="*" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
<!-- 繫結切面和切入點 -->
<aop:config>
<!-- 定義切入點表示式 -->
<aop:pointcut id="mycut" expression="execution(* com.example.service.impl.*.*(..))"/>
<!-- 將切面和切入點表示式繫結,為目標業務實現類中的業務方法提供對應的事務切面功能 -->
<aop:advisor advice-ref="myadvice" pointcut-ref="mycut"/>
</aop:config>
</beans>
package com.example.service.impl;
import com.example.mapper.UserMapper;
import com.example.pojo.Account;
import com.example.pojo.User;
import com.example.service.AccountService;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 業務實現類
*/
@Service
public class UserServiceImpl implements UserService {
//業務邏輯層實現類持有資料存取層的介面型別的變數
@Autowired
UserMapper userMapper;
//持有Account業務邏輯層的介面型別的變數
@Autowired
AccountService accountService;
@Override
public int insert(User user) {
int num = userMapper.insert(user);
if(num == 1){
System.out.println("使用者匯入成功!");
}else{
System.out.println("使用者匯入失敗!");
}
//巢狀呼叫賬戶的業務邏輯功能
accountService.save(new Account(25, "荷包蛋6","富婆的賬戶6"));
return num;
}
}
package com.example.test;
import com.example.pojo.User;
import com.example.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestUserAndAccount {
@Test
public void testUserAndAccount(){
//建立Spring容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext_trans.xml");
//獲取使用者的業務邏輯層物件
UserService userService = (UserService) ac.getBean("userServiceImpl");
//呼叫業務功能
userService.insert(new User(2, "荷包蛋2", "hanzhanghan2"));
}
}
<tx:method name="*save*" propagation="REQUIRED" no-rollback-for="ArithmeticException"/>
<tx:method name="*insert*" propagation="REQUIRED" no-rollback-for="ArithmeticException"/>
如果當宣告式註解所規劃的事務管理和某個業務層的業務方法對事務的個性化需求相沖突時,可以再另外開啟註解式事務並設定兩種事務的優先順序,達到優先使用註解式事務的目的。當order屬性的值越大,事務的優先順序越高
<!-- 新增註解式事務驅動-->
<tx:annotation-driven order="10" transaction-manager="transactionManager"/>
<aop:advisor order="1" advice-ref="myadvice" pointcut-ref="mycut"/>
不同技術對事務提交和回滾的實現簡單列舉如下,可見不同的技術使用的資料庫操作物件不同
JDBC:Connection con.commit(); con.rollback();
MyBatis:SqlSession sqlSession.commit(); sqlSession.rollback();
Hibernate:Session session.commit(); session.rollback();
使用事務管理器,目的就是為了生成相應技術下的資料庫連線 + 執行語句的物件
如果使用MyBatis框架,必須使用DataSourceTransactionManager類完成處理
<!-- 新增事務管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 由於事務管理必然要涉及到資料庫的操作,例如資料回滾等等,所以必須新增資料來源設定 -->
<property name="dataSource" ref="dataSource"/>
</bean>