Java – SpringAOP – 基于XML的声明式事务
简介
Spring 通过 XML 来配置 AOP切面SQL的声明式事务配置。
关于基于注解的声明式事务可以查看以下文章。
XML 声明式事务
将Spring配置文件中去掉tx:annotation-driven 标签,并添加配置:
<aop:config>
<!-- 配置事务通知和切入点表达式 -->
<aop:advisor advice-ref="txAdvice" pointcut="execution(* cn.unsoft.spring.tx.xml.service.impl.*.*(..))"></aop:advisor>
</aop:config>
<!-- tx:advice标签:配置事务通知 -->
<!-- id属性:给事务通知标签设置唯一标识,便于引用 -->
<!-- transaction-manager属性:关联事务管理器 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- tx:method标签:配置具体的事务方法 -->
<!-- name属性:指定方法名,可以使用星号代表多个字符 -->
<tx:method name="get*" read-only="true"/>
<tx:method name="query*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<!-- * 表示所有方法都进行配置事务 -->
<tx:method name="*" read-only="true"/>
<!-- read-only属性:设置只读属性 -->
<!-- rollback-for属性:设置回滚的异常 -->
<!-- no-rollback-for属性:设置不回滚的异常 -->
<!-- isolation属性:设置事务的隔离级别 -->
<!-- timeout属性:设置事务的超时属性 -->
<!-- propagation属性:设置事务的传播行为 -->
<tx:method name="save*" read-only="false" rollbackfor="java.lang.Exception" propagation="REQUIRES_NEW"/>
<tx:method name="update*" read-only="false" rollbackfor="java.lang.Exception" propagation="REQUIRES_NEW"/>
<tx:method name="delete*" read-only="false" rollbackfor="java.lang.Exception" propagation="REQUIRES_NEW"/>
</tx:attributes>
</tx:advice>
read-only
是否只读,如果一些需要写入数据库的操作,使用 read-only="true" 的话,将会报错。
timeout
超时查询数据库允许时间,默认 -1.即没有超时,但数据库一般都有自己的超时时间,所以如果是-1时,则按照数据库超时时间。
isolation
事务的隔离级别
数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题。一个事务与其他事务隔离的程度称为隔离级别。SQL标准中规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱。
隔离级别一共有四种:
读未提交:READ UNCOMMITTED
允许Transaction01读取Transaction02未提交的修改,如果Transaction02在此期间进行了回滚,那么Transaction01的数据将没有意义,称为【脏读】
读已提交:READ COMMITTED
要求Transaction01只能读取Transaction02已提交的修改。如果Transaction01初期读取的数据后,Transaction02又提交了事务修改数据,那么Transaction01所读取的数据与最新更新的数据不一样了,称为【不可重复读】
可重复读:REPEATABLE READ
确保Transaction01可以多次从一个字段中读取到相同的值,即Transaction01执行期间禁止其它事务对这个字段进行更新。在Transaction01读取期间会对字段进行加锁,这样Transaction02就不能修改这个字段,但Transaction02可以修改加锁以外的字段和表,这样有可能会使Transaction01加锁的字段产生变化,即使加了锁。称为【幻读】
串行化:SERIALIZABLE
确保Transaction01可以多次从一个表中读取到相同的行,在Transaction01执行期间,禁止其它事务对这个表进行添加、更新、删除操作。可以避免任何并发问题,但性能十分低下。
隔离级别 脏读 不可重复读 幻读
READ UNCOMMITTED 有 有 有
READ COMMITTED 无 有 有
REPEATABLE READ 无 无 有
SERIALIZABLE 无 无 无
各种数据库产品对事务隔离级别的支持程度:
隔离级别 Oracle MySQL
READ UNCOMMITTED × √
READ COMMITTED √(默认) √
REPEATABLE READ × √(默认)
SERIALIZABLE √ √
@Transactional(isolation = Isolation.DEFAULT) //使用数据库默认的隔离级别
@Transactional(isolation = Isolation.READ_UNCOMMITTED) //读未提交
@Transactional(isolation = Isolation.READ_COMMITTED) //读已提交
@Transactional(isolation = Isolation.REPEATABLE_READ) //可重复读
@Transactional(isolation = Isolation.SERIALIZABLE) //串行化
propagation
事务的传播行为,当出现A方法调用B方法时,A事务是否影响B事务的情况。
@Transactional(propagation = Propagation.REQUIRED)
默认值,A调用B,B需要事务,如果A有事务B就加入A的事务中,如果A没有事务,B就自己创建一个事务
@Transactional(propagation = Propagation.REQUIRED_NEW)
A调用B,B需要新事务,如果A有事务就挂起,B自己创建一个新的事务
@Transactional(propagation = Propagation.SUPPORTS)
A调用B,B有无事务无所谓,A有事务就加入到A事务中,A无事务B就以非事务方式执行
@Transactional(propagation = Propagation.NOT_SUPPORTS)
A调用B,B以无事务方式执行,A如有事务则挂起
@Transactional(propagation = Propagation.NEVER)
A调用B,B以无事务方式执行,A如有事务则抛出异常
@Transactional(propagation = Propagation.MANDATORY)
A调用B,B要加入A的事务中,如果A无事务就抛出异常
@Transactional(propagation = Propagation.NESTED)
A调用B,B创建一个新事务,A有事务就作为嵌套事务存在,A没事务就以创建的新事务执行
注意:基于xml实现的声明式事务,必须引入aspectJ的依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.1</version>
</dependency>
完整项目下载:
https://www. tzming.com/wp-content/uploads/2023/filesdown/Spring_TransferAccounts_xml.rar
共有 0 条评论