摘要:前言如題,今天介紹的聲明式事務。提供一個注解在配置類上來開啟聲明式事務的支持。而在配置里還開啟了對聲明式事務的支持,代碼如下所以在中,無須顯式開啟使用注解。源碼下載后語以上為聲明式事務的教程。
微信公眾號:一個優秀的廢人前言
如有問題或建議,請后臺留言,我會盡力解決你的問題。
如題,今天介紹 SpringBoot 的 聲明式事務。
Spring 的事務機制所有的數據訪問技術都有事務處理機制,這些技術提供了 API 用于開啟事務、提交事務來完成數據操作,或者在發生錯誤時回滾數據。
而 Spring 的事務機制是用統一的機制來處理不同數據訪問技術的事務處理,Spring 的事務機制提供了一個 PlatformTransactionManager 接口,不同的數據訪問技術的事務使用不同的接口實現,如下表:
數據訪問技術 | 實現 |
---|---|
JDBC | DataSourceTransactionManager |
JPA | JPATransactionManager |
Hibernate | HibernateTransactionManager |
JDO | JdoTransactionManager |
分布式事務 | JtaTransactionManager |
Spring 支持聲明式事務,即使用注解來選擇需要使用事務的方法,他使用 @Transactional 注解在方法上表明該方法需要事務支持。被注解的方法在被調用時,Spring 開啟一個新的事務,當方法無異常運行結束后,Spring 會提交這個事務。如:
@Transactional public void saveStudent(Student student){ // 數據庫操作 }
注意,@Transactional 注解來自于 org.springframework.transcation.annotation 包,而不是 javax.transaction。
Spring 提供一個 @EnableTranscationManagement 注解在配置類上來開啟聲明式事務的支持。使用了 @EnableTranscationManagement 后,Spring 容器會自動掃描注解 @Transactional 的方法與類。@EnableTranscationManagement 的使用方式如下:
@Configuration @EnableTranscationManagement public class AppConfig{ }注解事務行為
@Transactional 有如下表所示的屬性來定制事務行為。
屬性 | 含義 |
---|---|
propagation | 事務傳播行為 |
isolation | 事務隔離級別 |
readOnly | 事務的讀寫性,boolean型 |
timeout | 超時時間,int型,以秒為單位。 |
rollbackFor | 一組異常類,遇到時回滾。(rollbackFor={SQLException.class}) |
rollbackForCalssName | 一組異常類名,遇到回滾,類型為 string[] |
noRollbackFor | 一組異常類,遇到不回滾 |
norollbackForCalssName | 一組異常類名,遇到時不回滾。 |
@Transactional 不僅可以注解在方法上,還可以注解在類上。注解在類上時意味著此類的所有 public 方法都是開啟事務的。如果類級別和方法級別同時使用了 @Transactional 注解,則使用在類級別的注解會重載方法級別的注解。
SpringBoot 的事務支持自動配置的事務管理器
在使用 JDBC 作為數據訪問技術時,配置定義如下:
@Bean @ConditionalOnMissingBean @ConditionalOnBean(DataSource.class) public PlatformTransactionManager transactionManager(){ return new DataSourceTransactionManager(this.dataSource) }
在使用 JPA 作為數據訪問技術時,配置定義如下:
@Bean @ConditionalOnMissingBean(PlatformTransactionManager.class) public PlatformTransactionManager transactionManager(){ return new JpaTransactionManager() }
自動開啟注解事務的支持
SpringBoot 專門用于配置事務的類為 org.springframework.boot.autoconfigure.transcation.TransactionAutoConfiguration,此配置類依賴于 JpaBaseConfiguration 和 DataSourceTransactionManagerAutoConfiguration。
而在 DataSourceTransactionManagerAutoConfiguration 配置里還開啟了對聲明式事務的支持,代碼如下:
@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class) @Configuration @EnableTransactionManagement protected static class TransactionManagementConfiguration{ }
所以在 SpringBoot 中,無須顯式開啟使用 @EnableTransactionManagement 注解。
實戰演示如何使用 Transactional 使用異常導致數據回滾與使用異常導致數據不回滾。
準備工作:
SpringBoot 2.1.3
JDK 1.8
IDEA
pom.xml 依賴:
4.0.0 org.springframework.boot spring-boot-starter-parent 2.1.3.RELEASE com.nasus transaction 0.0.1-SNAPSHOT transaction transaction Demo project for Spring Boot 1.8 org.springframework.boot spring-boot-starter-data-jpa org.springframework.boot spring-boot-starter-web mysql mysql-connector-java runtime org.projectlombok lombok 1.16.20 org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-maven-plugin
代碼注釋很清楚,沒啥好說的。
application.yaml 配置:
spring: # u6570u636Eu5E93u76F8u5173 datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=true username: root password: 123456 # jpa u76F8u5173 jpa: hibernate: ddl-auto: update # ddl-auto:u8BBEu4E3A create u8868u793Au6BCFu6B21u90FDu91CDu65B0u5EFAu8868 show-sql: true
實體類:
import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @Entity @AllArgsConstructor @NoArgsConstructor public class Student { @Id @GeneratedValue private Integer id; private String name; private Integer age; }
dao 層
import com.nasus.transaction.domain.Student; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface StudentRepository extends JpaRepository{ }
service 層
import com.nasus.transaction.domain.Student; public interface StudentService { Student saveStudentWithRollBack(Student student); Student saveStudentWithoutRollBack(Student student); }
實現類:
import com.nasus.transaction.domain.Student; import com.nasus.transaction.repository.StudentRepository; import com.nasus.transaction.service.StudentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class StudentServiceImpl implements StudentService { @Autowired // 直接注入 StudentRepository 的 bean private StudentRepository studentRepository; // 使用 @Transactional 注解的 rollbackFor 屬性,指定特定異常時,觸發回滾 @Transactional(rollbackFor = {IllegalArgumentException.class}) @Override public Student saveStudentWithRollBack(Student student) { Student s = studentRepository.save(student); if ("高斯林".equals(s.getName())){ //硬編碼,手動觸發異常 throw new IllegalArgumentException("高斯林已存在,數據將回滾"); } return s; } // 使用 @Transactional 注解的 noRollbackFor 屬性,指定特定異常時,不觸發回滾 @Transactional(noRollbackFor = {IllegalArgumentException.class}) @Override public Student saveStudentWithoutRollBack(Student student) { Student s = studentRepository.save(student); if ("高斯林".equals(s.getName())){ throw new IllegalArgumentException("高斯林已存在,數據將不會回滾"); } return s; } }
代碼注釋同樣很清楚,沒啥好說的。
controller 層
import com.nasus.transaction.domain.Student; import com.nasus.transaction.service.StudentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/student") public class StudentController { // 注入 studentservice 的 bean @Autowired private StudentService studentService; // 測試回滾情況 @PostMapping("/withRollBack") public Student saveStudentWithRollBack(@RequestBody Student student){ return studentService.saveStudentWithRollBack(student); } // 測試不回滾情況 @PostMapping("/withOutRollBack") public Student saveStudentWithoutRollBack(@RequestBody Student student){ return studentService.saveStudentWithoutRollBack(student); } }Postman 測試結果
為了更清楚地理解回滾,以 debug (調試模式) 啟動程序。并在 StudentServiceImpl 的 saveStudentWithRollBack 方法上打上斷點。
測試前數據庫結果:
Postman 測試回滾
debug 模式下可見數據已保存,且獲得 id 為 1。:
繼續執行拋出異常 IllegalArgumentException,將導致數據回滾:
測試后數據庫結果:并無新增數據,回滾成功。
Postman 測試不回滾
測試前數據庫結果:
遇到 IllegalArgumentException 異常數據不會回滾:
測試后數據庫結果:新增數據,數據不回滾。
https://github.com/turoDog/Demo/tree/master/springboot_transaction_demo
后語以上為 SpringBoot 聲明式事務的教程。最后,對 Python 、Java 感興趣請長按二維碼關注一波,我會努力帶給你們價值,如果覺得本文對你哪怕有一丁點幫助,請幫忙點好看,讓更多人知道。
另外,關注之后在發送 1024 可領取免費學習資料。資料內容詳情請看這篇舊文:Python、C++、Java、Linux、Go、前端、算法資料分享
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/73359.html
摘要:準備階段以上一篇文章的代碼為例子,即整合,上一篇文章是基于注解來實現的數據訪問層,這篇文章基于的來實現,并開啟聲明式事務。創建實體類數據訪問層接口層用戶減塊用戶加塊,聲明事務,并設計一個轉賬方法,用戶減塊,用戶加塊。 springboot開啟事務很簡單,只需要一個注解@Transactional 就可以了。因為在springboot中已經默認對jpa、jdbc、mybatis開啟了事事...
摘要:支持聲明式事務,通過注解控制方法是否支持事務。聲明式事務,基于實現,將具體業務和業務邏輯解耦。該級別下事務順序執行,阻止上面的缺陷,開銷很大。 問題引入 Spring中事務傳播有哪幾種,分別是怎樣的? 理解注解事務的自動配置? SpringBoot啟動類為什么不需要加@EnableTransactionManagement注解? 聲明式事務的實現原理?(待補充) ...
閱讀 3736·2023-04-25 18:41
閱讀 1169·2021-11-11 16:55
閱讀 1823·2021-09-22 15:54
閱讀 3069·2021-09-22 15:51
閱讀 3545·2019-08-30 15:55
閱讀 1937·2019-08-30 14:19
閱讀 1277·2019-08-29 10:57
閱讀 1699·2019-08-29 10:56