zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Spring——声明式事务详解编程语言

Spring事务编程语言 详解 声明
2023-06-13 09:11:53 时间

Spring的声明式事务使用起来比较简单,[email protected],就将一个方法变成事务方法了。使用声明式事务,可以将事务管理代码从业务方法中抽离出来(也就是不用在方法里写commit和rollback),以声明的方式来实现事务管理。

Spring的核心事务管理抽象是PlatformTransactionManager,要想使用声明式事务,必须先在xml中先将其声明为bean,而且还要记得配置数据源

 !--这么写就可以扫描到db.properties的配置信息-- 

 context:property-placeholder location="classpath:db.properties" /context:property-placeholder 

 !--配置数据源-- 

 bean id = "dataSource" class = "com.alibaba.druid.pool.DruidDataSource" 

 property name="username" value="${jdbc.username}" /property 

 property name="password" value="${jdbc.password}" /property 

 property name="url" value="${jdbc.url}" /property 

 property name="driverClassName" value="${jdbc.driverName}" /property 

 /bean 

 !--配置事务管理器的bean对象-- 

 bean id="transactionManager" 

 property name="dataSource" ref="dataSource" /property 

 /bean 

 !--如果代码中用到jdbc操作数据库,可以加下面的配置-- 

 !--将JdbcTemplate注册为bean-- 

 bean id="jdbcTemplate" 

 property name="dataSource" ref="dataSource" /property 

 /bean 

 !--开启事务管理器的配置-- 

 tx:annotation-driven transaction-manager="transactionManager" /tx:annotation-driven 

#db.properties 

jdbc.username = root 

jdbc.password = root 

jdbc.url = jdbc:mysql://localhost:3306/tx 

jdbc.driverName = com.mysql.jdbc.Driver 

@Transactional

下面说明一下Transactional里的重要参数


ioslation:隔离级别。可配置为可重复读,读已提交,读未提交,序列化,DEFAULT(这个配置将使用选择的数据库的默认事务隔离级别)


rollbackFor:指定一个或多个异常,当方法发生这个异常时,回滚
如 @Transactional(rollbackFor = {java.lang.ArithmeticException.class})。这一项,强烈建议每个声明式事务都必须配置


rollbackForClassName:与上同,只是传参形式不同
如@Transactional(noRollbackForClassName = "java.lang.ArithmeticException")


noRollbackFor:指定一个或多个异常,当方法发生这个异常时,不回滚
如 @Transactional(noRollbackFor = {java.lang.ArithmeticException.class})


noRollbackForClassName:与上同,只是传参形式不同
如 @Transactional(noRollbackForClassName = "java.lang.ArithmeticException")


事务的传播特性

传播特性:表示不同事务之间执行的关系。或者说当一个事务方法A被另一个事务方法B调用时,A和B会发生怎样的关系

下面的文字比较绕,如果看不懂(一般人都看不懂…)直接看下面的例子解释就行
在这里插入图片描述
注意下面所有multi方法与buyBook和updatePrice不在一个类中。若在一个类,multi对buyBook和updatePrice的调用将会是普通调用,不会产生事务传播特性

REQUIERD(这是默认传播特性)
 @Transactional() 

 public void multi(){

 bookService.buyBook(); [email protected](propagation = Propagation.REQUIRED) 

 bookService.updatePrice(BOOK_ID); [email protected](propagation = Propagation.REQUIRED) 

REQUIRED的效果是:当内部的事务方法配置了REQUIRED之后,事务的控制交由外部事务方法(multi)控制。也就是说,将buyBook和updatePrice统一成一个事务,只有buyBook和updatePrice都commit时,整个multi才算commit。不论buyBook还是updatePrice发生异常(不论是否在multi被try-catch捕获),二者都会rollback,一个都不会commit。如果取消multi的事务声明使之变为普通方法,那么buyBook和updatePrice,谁发生异常谁rollback,不影响另一个方法的commit

REQUIRES_NEW
 @Transactional() 

 public void multi(){

 bookService.buyBook(); [email protected](propagation = Propagation.REQUIRES_NEW) 

 bookService.updatePrice(BOOK_ID); [email protected](propagation = Propagation.REQUIRED) 

REQUIRES_NEW的效果是:配置成REQUIRES_NEW的方法会单独执行一个事务,若buyBook发生异常(不论是否被try-catch捕获),则buyBook会rollback,不影响updatePrice的commit。从REQUIRES_NEW这一名字就可联想到,配成REQUIRES_NEW的方法,需要一个新事务单独执行,而由于事务的隔离性,所以配成REQUIRES_NEW的事务不会影响其他事务,即使它们被捆绑到同一个事务方法(multi)里

SUPPORTS
 @Transactional() 

 public void multi(){

 bookService.buyBook(); [email protected](propagation = Propagation.SUPPORTS) 

SUPPORTS的效果是:如果multi是事务方法,则buyBook受事务控制。如果multi是普通方法,则buyBook不受事务控制(即,发生异常的代码前的逻辑会成功commit,发生异常代码后的逻辑会报错失败)。SUPPORTS方式几乎不用

NOT_SUPPORTED
 @Transactional() 

 public void multi(){

 bookService.buyBook(); [email protected](propagation = Propagation.NOT_SUPPORTED) 

NOT_SUPPORTED的效果是:不论multi是不是事务方法,buyBook均不受事务控制(即,发生异常的代码前的逻辑会成功commit,发生异常代码后的逻辑会报错失败)。NOT_SUPPORTED方式几乎不用

MANDATORY
 [email protected]() 

 public void multi(){

 bookService.buyBook(); [email protected](propagation = Propagation.NEVER) 

NEVER的效果是:必须在buyBook外面再套一层事务方法,否则会报下列错误。MANDATORY几乎不用(唯一的用处可能就是,强制让其他程序员在使用buyBook时,必须要与其他事务一起使用,捆绑在一个事务里)在这里插入图片描述

NEVER
 @Transactional() 

 public void multi(){

 bookService.buyBook(); [email protected](propagation = Propagation.NEVER) 

NEVER的效果是:不允许buyBook外面再套一层事务方法,否则会报下列错误。NEVER与MANDATORY正好相反。NEVER方式几乎不用(唯一的用处可能就是,强制让其他程序员在使用buyBook时,不允许再在外层套一个事务方法)
在这里插入图片描述

NESTED
 @Transactional(rollbackFor = {

 java.lang.ClassCastException.class}) 

 public void multi(){

 try {

 bookService.buyBook();[email protected](propagation = Propagation.NESTED) 

 }catch(Exception e){

 bookService.updatePrice(BOOK_ID);[email protected] 

 int i = 1/0; 

NEVER的效果是:如果buyBook方法发生异常(updatePrice无异常),不被捕获,则buyBook和updatePrice都不会回滚。可是如果buyBook被捕获了,并且multi发生异常时,则buyBook和updatePrice都会回滚。一句话说就是:NESTED的配置会导致,不论multi里怎么对异常方法处理了,所有方法均会回滚。换言之,multi里的所有方法,都被multi里都异常所制约

对REQUIRED,REQUIRES_NEW,NESTED做一个区别

REQUIRED:将所有事务方法捆绑为一个事务,一荣俱荣,一殒具殒 REQUIRES_NEW:单独将配置成REQUIRES_NEW的那个事务视为独立的事务,不管它有没有被捆绑到外部事务中,不管外部事务是否发生异常,它的成功commit与否,均与其他事务无关。 NESTED:不论被捆绑的事务在外部事务中做了怎样的异常捕获,均被外部事务中的异常所制约,一旦外部事务发生异常,所有捆绑到外部事务中的事务,都要回滚。

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/20577.html

cjavamysqlxml