目录
1.基于XML的配置方式:通过在Spring的配置文件(如applicationContext.xml)中定义事务管理器、事务通知(Advice)、切点(Pointcut)和事务属性等信息来实现。
2.基于注解的配置方式:通过在Java类或方法上使用@Transactional注解来声明事务属性。这种方式更为简洁和直观。
1.1什么是事务?
事务是指作为单个逻辑工作单元执行的一系列操作,要么全部成功提交,要么全部失败回滚。
·事务的作用:当操作序列中某个操作失误时,提供一种方式使操作恢复正常状态,保持数据一致性(要么操作失败前的正常状态,要么操作成功后的新状态)。
1.1.1事务特性(ACID)
事务有四大特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
原子性:一个事务在进行操作时要么全执行要么全不执行。事务若执行中出现错误,则回滚到事务开始前的状态。
一致性:在事务开始前和完成后,数据的完整性肯定是一致的。以保证后续操作。
隔离性:事务的隔离性表示多个用户并发同时访问数据时,数据库为每个用户开启的事务不会被其他用户干扰,防止并发执行时使数据不一致。
持久性:一旦事务提交后,他对数据库中数据的改变是永久的,即使数据库发生故障也无妨。
1.1.2事务的隔离级别
1.脏读:(READ UNCOMMITTED)读未提交,该隔离级别的事务可以看到其他事务中未提交的数据。可以读取其他事务中未提交的数据,未提交则可能回滚,此时读取得到的数据的过程叫做脏读.
2.不可重复读:( REPEATABLE READ)它指的是在同一个事务内,由于其他事务修改了数据,导致同一个查询语句在不同时间点执行时,返回的结果集不一致的情况。
3.幻读:(SERIALIABLE)它指的是在一个事务中,由于其他事务插入或删除了一些数据,导致同一个查询语句在不同时间点执行时,返回的结果集不一致的情况。
1.2Spring事务管理的核心对象
1.Platform TransactionManager
Spring 框架提供了多种实现 PlatformTransactionManager
接口的类,每种实现适用于不同的事务管理场景:
-
DataSourceTransactionManager:最常用的事务管理器,用于管理基于 JDBC 的事务。
-
JpaTransactionManager:用于管理基于 JPA(Java Persistence API)的事务。
-
HibernateTransactionManager:用于管理基于 Hibernate 的事务。
-
JtaTransactionManager:用于管理分布式事务,基于 JTA(Java Transaction API)。 此接口定义了事物的基本操作
-
获取事务 TransactionStatus getTransaction(TransactionDefinition definition)
-
提交事务:void commit(TransactionStatus status)
-
回滚事务:void rollback(TransactionStatus status)
2.TransactionDefinition
-
获取事务定义名称 String getName()
-
获取事务读写属性:boolean isReadOnly()
-
获取事务隔离级别:int getIsolationLevel()
-
获取事务超时时间:int getTimeout()
1.3事务的控制方式
主要分为编程式和声明式
1.3.1Spring编程式事务管理:
一种通过编程的方式来控制事务的提交、回滚和管理的方法,相对于声明式事务管理而言,更多地依赖于编写代码来显式地控制事务的边界和操作。在使用编程式事务管理时,通常需要显式地调用事务管理器的方法来开始事务、提交事务或者回滚事务,从而控制事务的执行过程。
步骤:获取、提交、回滚
示例:
首先,通过 transactionManager.getTransaction(txDefinition)
方法获取了一个 TransactionStatus
对象来表示当前事务的状态。然后,在 try-catch
块中执行业务逻辑,根据业务逻辑的成功与否来决定是调用 transactionManager.commit(txStatus)
提交事务,还是在出现异常时调用 transactionManager.rollback(txStatus)
回滚事务。
public class ProgrammaticTransactionExample {
private PlatformTransactionManager transactionManager;
// 设置事务管理器
public void setTransactionManager(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
public void performTransactionalOperation() {
// 定义事务属性
DefaultTransactionDefinition txDefinition = new DefaultTransactionDefinition();
// 获取事务状态对象
TransactionStatus txStatus = transactionManager.getTransaction(txDefinition);
try {
// 执行业务逻辑,可能包含多个数据库操作
// 例如:dao.save(entity);
// 根据业务逻辑成功与否决定提交或回滚事务
if (/* 业务逻辑成功 */) {
transactionManager.commit(txStatus);
} else {
transactionManager.rollback(txStatus);
}
} catch (Exception ex) {
// 捕获异常,标记事务为回滚状态
transactionManager.rollback(txStatus);
throw ex;
}
}
}
1.3.2Spring声明式事务
声明式事务管理是一种通过配置而非编程实现事务管理的方法。在声明式事务管理中,开发人员通过配置文件或注解来定义事务的边界和属性,而不需要在业务代码中显式地管理事务的开始、提交和回滚操作。
在Java应用程序中,Spring框架广泛使用声明式事务管理。通过Spring的AOP(面向切面编程)技术,可以在方法调用前后自动添加事务管理的逻辑,而无需修改业务方法的代码。
1.基于XML的配置方式:通过在Spring的配置文件(如applicationContext.xml)中定义事务管理器、事务通知(Advice)、切点(Pointcut)和事务属性等信息来实现。
<beans xmlns="http://www.springframework.org/schema/beans"
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/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- 配置切点 -->
<aop:config>
<aop:pointcut id="serviceMethods" expression="execution(* com.example.service.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/>
</aop:config>
</beans>
2.基于注解的配置方式:通过在Java类或方法上使用@Transactional
注解来声明事务属性。这种方式更为简洁和直观。
在需要的⽅法上添加 @Transactional 注解即可,⽆需⼿动开启事务和提交事务,进⼊⽅法时⾃动开启事务,⽅法执⾏完会⾃动提交事务,如果中途发⽣了没有处理的异常会⾃动回滚事务。
@Service
@Transactional
public class UserService {
@Autowired
private UserRepository userRepository;
public void saveUser(User user) {
userRepository.save(user);
}
@Transactional(readOnly = true)
public User getUser(Long userId) {
return userRepository.findById(userId).orElse(null);
}
}
无论是XML配置方式还是注解方式,声明式事务管理都能有效地简化事务管理的实现,提升了代码的可读性和可维护性,是开发中常用的一种实践方式。
1.4事务的传播机制
当指定了在方法调用链中已存在事务时,新的事务如何传播到当前方法中。这些传播行为可以通过@Transactional
注解的propagation
属性来进行配置。
-
REQUIRED(默认行为):如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
-
SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式执行。
-
MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
-
REQUIRES_NEW:无论当前是否存在事务,都创建一个新的事务。如果当前存在事务,则将其挂起。
-
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则将其挂起。
-
NEVER:以非事务方式执行操作,如果当前存在事务,则抛出异常。
-
NESTED:如果当前存在事务,则在嵌套事务内执行。嵌套事务是当前事务的一部分,它有自己的保存点。如果主事务提交,则嵌套事务也会提交,但是如果嵌套事务失败而回滚,则只会回滚到嵌套事务的保存点。
总结
Spring框架的事务管理提供了一种简单且强大的方式来管理数据库事务。主要总结为以下几点:
-
事务管理器(Transaction Manager):
Spring通过事务管理器来管理事务的开始、提交、回滚和状态控制。PlatformTransactionManager
是其核心接口,不同的数据访问技术(如JDBC、Hibernate、JPA等)有不同的实现,比如DataSourceTransactionManager
、JpaTransactionManager
等。 -
声明式事务管理:
Spring支持声明式事务管理,通过注解或XML配置来简化事务管理的实现。常用的注解包括@Transactional
,可以应用在类级别或方法级别,用于标识哪些方法需要进行事务管理。 -
事务传播行为(Transaction Propagation):
定义了在嵌套调用中如何传播事务的行为。例如,当前方法调用另一个标记为@Transactional
的方法时,事务如何传播。 -
事务隔离级别(Isolation Level):
定义了事务在并发环境下的隔离程度,包括读未提交、读已提交、可重复读和串行化等级别。
Spring的事务管理使得开发者可以集中精力于业务逻辑的实现,而不必过多关注事务管理的细节,同时提供了灵活和可配置的选项来适应不同的应用需求和数据访问技术。
以上为本人在学习Spring事务过程中的理解与解释。