Spring 事务使用详解

相关文章

Spring AOP 创建代理的源码解析

Spring AOP 注解方式源码解析

Spring AOP 功能使用详解

Spring 的 getBean 方法源码解析

Spring bean 创建过程源码解析

Spring 中 bean 注册的源码解析

前言

 什么是事务?根据 维基百科事务 介绍,数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。简单来说,事务就是将一系列操作当成一个不可拆分的执行逻辑单元,这些要么都成功,要么都失败。事务具有4个属性:原子性、一致性、隔离性、持久性。称为ACID特性。

Spring 事务

在使用 Spring 进行开发过程中,一般都会使用 Spring 来进行事务的控制,接下来就来看下 Spring 使用事务的详细过程,包括事务的传播方式等。本文根据官方文档 的介绍,结合例子来进行说明。

Spring 事务支持两种方式,编程式事务和声明式事务,下面的栗子会使用声明式事务来举例,即使用 @Transactional 注解的方式

栗子

首先来看个简单栗子,后面再来对事务的一些属性进行详细的分析和介绍。

1. 首先来看下两个数据库表结构 user 表和 address 表:

user 表:

0f762ae1acf1177d937b95c2d78d8a84998.jpg

address 表:

552199a99f6e690b269304f689a1ee7abf3.jpg

2. Spring 配置文件启动事务:

<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
	<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
	<property name="url" value="jdbc:mysql://localhost:3306/tsmyk"/>
	<property name="username" value="root"/>
	<property name="password" value="root"/>
</bean>

3. 定义需要事务执行的方法:

接口

public interface IUserService {
    void add(User user) throws RuntimeException;
}

实现类:

public class UserServiceImpl implements IUserService {

    private JdbcTemplate jdbcTemplate;
    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    @Transactional
    @Override
    public void add(User user) throws RuntimeException {
        String sql = "insert into user(name, age, sex, money, job) values (?, ?, ?, ?, ?)";
        Object[] args = new Object[]{user.getName(), user.getAge(),user.getSex(),user.getMoney(), user.getJob()};
        jdbcTemplate.update(sql, args);
        throw new RuntimeException("保存出现异常...");
    }
}

这里使用 JdbcTemplate 来操作数据库

4. 在上述的配置文件中配置该 bean:

<bean id="txUserService" class="main.tsmyk.transaction.UserServiceImpl">
    <property name="dataSource" ref="dataSource"/>
</bean>

5. 单元测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/resources/myspring.xml")
public class TestTransaction {
    
    @Autowired
    private IUserService userServiceImpl;

    @Test
    public void test1() throws RuntimeException {
        User user = new User("xiaoqi", 20, 1, 1000, "java");
        userServiceImpl.add(user);
    }
}

6. 运行结果会抛出异常:

76464c493c95e82d8154c868c47971a6999.jpg

7. 此时数据库的数据还是原来的,数据插入失败:

3815dd98b4b3b6bdfb9d733de1abb385cd3.jpg

上述的栗子中,在 add() 方法加上了事务注解 @Transactional ,当该方法抛出异常的时候,数据库会进行回滚,数据插入失败。

事务原理

Spring 事务是使用 AOP 来实现的,在 Spring AOP 注解方式源码解析 和 Spring AOP 创建代理的源码解析 文章中,了解到,在执行目标方法之前和之后,我们可以进行一些增强操作,而这恰恰可以符合事务的使用情况,在目标方法执行成功后,提交事务,失败的时候,回滚事务。当然,我们还可以通过 AOP 来自定义事务的行为。从概念上讲,在事务代理上调用方法看起来如下所示:

58e5e3f5ea0244d2e950f069247c2a302f8.jpg

当客户端调用的时候,调用的是代理对象,在执行目标方法之前,会创建事务,即事务增强,之后会执行我们自

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值