7种数据库事务传递性代码实例详解

6 篇文章 0 订阅

首先MySQL建立测试表,只是测试用所以比较简单

test_isolation

+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | YES  |     | NULL    |       |
| num   | int(11) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
test_propagation

+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | YES  |     | NULL    |       |
| num   | int(11) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+

项目采用maven+maven创建,junit单元测试运行测试

概念

本地事务

       数据库事务,默认事务为自动提交,因此如果一个业务逻辑类中有多次数据库操作将无法保证事务的一致性。

Spring事务

       对本地事务操作的一次封装,相当于把使用JDBC代码开启、提交、回滚事务进行了封装。

上述两个概念会在demo中用到,以方便大家理解代码。

事务传播性:

1、PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。

2、PROPAGATION_SUPPORTS自身不会开启事务,在事务范围内则使用相同事务,否则不使用事务。‘

3、PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。

4、PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。

5、PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

6、PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。

7、PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。


Junit单元测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:applicationContext.xml"})
public class TestPropagation {


    @Autowired
    private ITestIsolationService isolationService;

    @Autowired
    private ITestPropagationService propagationService;

    @Test
    public void testPropagation() {
        isolationService.add("insert test_isolation values(1,1)");
    }
}

业务层代码都是使用spring的JdbcTemplate操作

PROPAGATION_REQUIRED

    // TestIsolationServiceImpl
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void add(String sql) {
        jdbcTemplate.execute(sql);

        propagationService.add("insert test_propagation values(1,1)");

        throw new RuntimeException();
    }

    // TestPropagationServiceImpl
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void add(String sql) {
        jdbcTemplate.execute(sql);
    }

经测试无论在isolationservice还是propagationservice如果不抛出异常,那么数据提交成功,如果抛出异常,数据提交失败。这说明isolationservice和propagationservice使用的是同一个事务,并且只要方法被调用就开启事务。


PROPAGATION_REQUIRES_NEW

    // TestIsolationServiceImpl
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public void add(String sql) {
        jdbcTemplate.execute(sql);

        propagationService.add("insert test_propagation values(1,1)");

        throw new RuntimeException();
    }

    // TestPropagationServiceImpl
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public void add(String sql) {
        jdbcTemplate.execute(sql);
    }

经测试如果在isolationservice中抛出异常,isolationservice数据不能正确提交,propagationservice被正确提交。说明isolationservice和propagationservice是在两个独立的事务中运行,并且只要方法被调用就开启事务。

PROPAGATION_SUPPORTS

    // TestIsolationServiceImpl
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public void add(String sql) {
        jdbcTemplate.execute(sql);

        propagationService.add("insert test_propagation values(1,1)");

        throw new RuntimeException();
    }

    // TestPropagationServiceImpl
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public void add(String sql) {
        jdbcTemplate.execute(sql);
    }

经测试如果在isolationservice中抛出异常,isolationservice和propagationservice都被正确提交。说明isolationservice和propagationservice没有被spring管理和开启事务,而是使用了本地事务,由于本地事务默认自动提交因此数据都提交成功,但它们使用的却不是同一个事务,一旦出现异常将导致数据的不一致。


PROPAGATION_NOT_SUPPORTED

    // TestIsolationServiceImpl
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    @Override
    public void add(String sql) {
        jdbcTemplate.execute(sql);

        throw new RuntimeException();
    }

经测试如果在isolationservice中抛出异常,isolationservice正确提交。说明isolationservice没有被spring管理和开启事务,而是使用了本地事务,由于本地事务默认自动提交因此数据都提交成功。


其他几种大家可以自行测试,demo代码已经上传至git,其中demo中还有zookeeper,dubbo,rabbitmq,webservice,aop,等等一系列的测试用力,大家可以参考

代码地址:https://git.coding.net/scott-huo/product.git,git@git.coding.net:scott-huo/product.git

有问题可以加群询问,共同探讨学习


  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心所向皆可成

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值