【揭秘】Spring框架中的两大事务管理神器:声明式与编程式!

在Spring框架中,事务管理是一个非常重要的部分,它主要用来确保数据的完整性和一致性。Spring支持声明式事务管理和编程式事务管理两种方式。

声明式事务管理

声明式事务管理是基于AOP实现的,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式来管理事务,只需在配置文件中做相关的事务规则声明或通过注解方式,就可以将事务规则应用到业务逻辑中。

Spring的声明式事务管理在底层是建立在AOP的基础之上的。其管理事务的主要是通过Spring AOP和IOC容器实现的。其中AOP是面向切面编程,可以让我们在不修改源代码的基础上对已有方法进行增强处理。而IOC容器是Spring的核心,其负责管理所有的Java对象,包括事务管理器、数据源、业务逻辑对象等等。

编程式事务管理

编程式事务管理是通过编程代码手动管理事务,包括开启事务、提交事务、回滚事务等。Spring的编程式事务管理可以通过PlatformTransactionManager接口和TransactionDefinition接口来实现。我们可以通过实现PlatformTransactionManager接口来自定义我们的事务管理器,也可以通过TransactionTemplate类来简化编程式事务管理的代码。

代码演示

接下来通过代码进行演示,假设你在Spring的配置文件中配置事务管理器,你使用的是基于JDBC的数据源,配置可能如下:

xml 复制代码
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>  
    <property name="url" value="jdbc:mysql://localhost:3306/test"/>  
    <property name="username" value="root"/>  
    <property name="password" value="password"/>  
</bean>  
  
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
    <property name="dataSource" ref="dataSource"/>  
</bean>  
  
<tx:annotation-driven transaction-manager="transactionManager"/>

首先是,声明式事务管理 ,在你的业务逻辑类中使用@Transactional注解来声明需要事务管理的方法。例如:

java 复制代码
import org.springframework.transaction.annotation.Transactional;  
import org.springframework.stereotype.Service;  
  
@Service  
public class UserService {  
    private final UserRepository userRepository;  
  
    @Autowired  
    public UserService(UserRepository userRepository) {  
        this.userRepository = userRepository;  
    }  
  
    @Transactional  
    public void createUser(User user) {  
        userRepository.save(user);  
        // ... 其他业务逻辑,如发送通知等  
    }  
}

在上述代码中,createUser方法上的@Transactional注解告诉Spring该方法需要在事务中执行。Spring将负责在方法开始执行时开启事务,并在方法执行完毕时提交或回滚事务。这种方式无需手动编写事务管理代码,而是通过注解来声明事务规则,实现了声明式事务管理。

接着,是编程式事务管理 ,编程式事务管理需要手动编写代码来管理事务。以下是一个使用Spring的TransactionTemplate类进行编程式事务管理的示例:

java 复制代码
import org.springframework.transaction.TransactionStatus;  
import org.springframework.transaction.support.TransactionCallbackWithoutResult;  
import org.springframework.transaction.support.TransactionTemplate;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.stereotype.Service;  
  
@Service  
public class UserService {  
    private final TransactionTemplate transactionTemplate;  
    private final UserRepository userRepository;  
  
    @Autowired  
    public UserService(TransactionTemplate transactionTemplate, UserRepository userRepository) {  
        this.transactionTemplate = transactionTemplate;  
        this.userRepository = userRepository;  
    }  
  
    public void createUser(User user) {  
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {  
            @Override  
            protected void doInTransactionWithoutResult(TransactionStatus status) {  
                try {  
                    userRepository.save(user);  
                    // 其他业务逻辑  
                    status.setRollbackOnly(); // 设置回滚事务,如果需要的话  
                } catch (Exception e) {  
                    status.setRollbackOnly(); // 发生异常时回滚事务  
                    throw e; // 重新抛出异常,由上层处理  
                }  
            }  
        });  
    }  
}

在上述代码中,createUser方法使用TransactionTemplate类来执行需要在事务中运行的代码。通过调用transactionTemplate.execute方法,传入一个实现TransactionCallbackWithoutResult接口的匿名类,在匿名类的doInTransactionWithoutResult方法中编写需要在事务中执行的代码。这种方式需要手动管理事务的开启、提交和回滚,实现了编程式事务管理。这种方式更加灵活,可以根据具体需求进行更精细的事务控制。

最后总结

声明式事务管理利用@Transactional注解简化了事务管理的复杂性,免去了手动编写事务管理代码的繁琐。但是,当事务函数内部需要捕获异常时,由于@Transactional的默认行为是在遇到运行时异常时回滚,如果异常被捕获并未再次抛出,事务可能无法正确回滚,这是其主要的缺点。

编程式事务管理要求开发者手动编写事务管理的代码,尽管这增加了开发的工作量,但它为开发者提供了更大的灵活性。例如,开发者可以根据特定的业务逻辑,在事务中的任意位置进行提交或回滚操作。此外,当某些特定的异常发生时,编程式事务管理允许开发者精确地决定是提交还是回滚事务,这种控制能力是编程式事务管理的明显优势。

相关推荐
向上的车轮33 分钟前
云边端架构的优势是什么?面临哪些挑战?
架构·云边端
FHYAAAX38 分钟前
灾备方案和架构类型、跨区域
架构·华为云
北京_宏哥1 小时前
python接口自动化(四十二)- 项目架构设计之大结局(超详解)
python·架构·前端框架
车载诊断技术10 小时前
电子电气架构 --- 什么是EPS?
网络·人工智能·安全·架构·汽车·需求分析
武子康10 小时前
大数据-258 离线数仓 - Griffin架构 配置安装 Livy 架构设计 解压配置 Hadoop Hive
java·大数据·数据仓库·hive·hadoop·架构
9527华安15 小时前
FPGA多路MIPI转FPD-Link视频缩放拼接显示,基于IMX327+FPD953架构,提供2套工程源码和技术支持
fpga开发·架构·音视频
三桥彭于晏21 小时前
B/S 跟C/S架构的区别
架构
小蜗牛慢慢爬行1 天前
如何在 Spring Boot 微服务中设置和管理多个数据库
java·数据库·spring boot·后端·微服务·架构·hibernate
小扳1 天前
微服务篇-深入了解 MinIO 文件服务器(你还在使用阿里云 0SS 对象存储图片服务?教你使用 MinIO 文件服务器:实现从部署到具体使用)
java·服务器·分布式·微服务·云原生·架构
盛派网络小助手1 天前
微信 SDK 更新 Sample,NCF 文档和模板更新,更多更新日志,欢迎解锁
开发语言·人工智能·后端·架构·c#