编程式事务 (Java)

编程式事务
开始 :

Spring可以支持编程式事务和声明式事务。
Spring提供的最原始的事务管理方式是基于TransactionDefinition、PlatformTransactionManager、TransactionStatus 编程式事务。
TransactionTemplate的编程式事务管理是使用模板方法设计模式对原始事务管理方式的封装。

为什么要使用编程式事务?

编程式事务是一种在数据库操作中使用的事务处理方式,通过编写程序来控制事务的提交或回滚。与声明式事务相比,编程式事务需要手动指定事务的启动、提交和回滚等操作,具有更精细的控制能力。

以下是一些使用编程式事务的优点:

灵活性: 编程式事务可以根据业务逻辑和数据操作的复杂度进行灵活的控制和处理,保证数据的一致性和完整性;

可读性: 编程式事务代码可以直接显示了事务的边界和执行顺序,方便理解和调试;

安全性: 使用编程式事务可以防止数据库死锁和数据冲突等问题,在多并发访问中保障数据的安全和可靠性;

跨框架支持: 编程式事务可以跨框架地使用,不依赖于任何特定的框架或容器,使得开发人员可以自由地选择合适自己的工具进行开发和部署;

增量修改: 使用编程式事务时,可以控制每个事务的大小和影响范围,因此在大型系统需求变化频繁的情况下很有用,能够更方便地新增或修改系统的某些功能,而不会对整个系统造成影响。

当然,使用编程式事务也有一些缺点,如代码冗长、可维护性差等问题,需要在使用时权衡利弊并根据业务需求选择最佳的事务处理方式。

个人是因为业务需求原因而选择了它,举例如下:

// 原代码
@Transactional(rollbackFor = Exception.class)
public Boolean alterOperation(Object obj){
// 查询操作1
object1 = service.select();
// 数据处理
.......
// 查询操作2
object2 = service.select2();
// 查询操作3
object3 = service.select3();
.....
// 此处省略查询操作与逻辑......

// 最后增删改操作.....
boolean rs = update();
}

我们可以看到上面方法使用注解开启了事务,并且是一个相对较长的事务,整个方法做了大量的查询等逻辑操作,如果查询很复杂,时查询时长较长加剧对系统资源和性能的影响.所以在这尽量缩短事务执行的时间,让其他查询可以更快的获得资源和锁.
我们现在可以做的就是:

拆分长事务:我们应该尽可能将一个长过程拆分为多个短小的事务,确保每个事务只关注它所需的数据和逻辑,避免将不必要的其他资源锁定在事务中;

降低事务隔离级别:将隔离级别从最高级别(如Serializable)降低到更低的级别(如Read Committed),可以减少锁的数量和范围,提高并发性能,但也可能会带来数据一致性问题,需要评估风险进行决策;

使用乐观锁:在更新记录时,我们可以使用乐观锁技术,即先读取记录并将其版本号或时间戳等信息保存在变量中,然后进行修改时检查该记录是否被其他事务更新过,如果没有就执行更新操作。这种方式可以避免使用悲观锁占用太多资源

合理设计数据库架构:合理的表设计和索引设计能够减小锁的粒度,启用分区表或者sharding也可以使得数据无需跨越多个节点查询。


下面使用编程式事务来拆分长事务

基础使用: 减少事务粒度,防止查询长时间阻塞.

# 引用注入 事务模板
@Autowired
private TransactionTemplate transactionTemplate;

# 在需要添加事务方法里编写代码
public Boolean test(){
    // 各种查询代码
    // 开启事务
    Boolean rs = transactionTemplate.execute(transactionStatus -> {
        return Boolean.TRUE; 或者 return Boolean.FALSE;
    }
}

所以当我们借助TransactionTemplate.execute( … )执行事务管理的时候,传入的参数有两种选择:
1、TransactionCallback
2、TransactionCallbackWithoutResult

两种区别从命名看就相当明显了,一个是有返回值,一个是无返回值。这个的选择就取决于你是读还是写了。

例子:
借助(TransactionCallback)执行事务管理,既带有返回值:

public Object getObject(String str) {
        /*
         *  执行带有返回值<Object>的事务管理
         */
        transactionTemplate.execute(new TransactionCallback<Object>() {
            @Override
            public Object doInTransaction(TransactionStatus transactionStatus) {
                try {
                      ...
                    //.......   业务代码
                    return new Object();
                } catch (Exception e) {
                    //回滚
                    transactionStatus.setRollbackOnly();
                    return null;
                }
            }
        });
}

借助(TransactionCallbackWithoutResult)执行事务管理,既无返回值:

public void update(String str) {

         /*
         *  执行无返回值的事务管理
         */
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {

                try {

                    // ....  业务代码
                } catch (Exception e){
                    //回滚
                    transactionStatus.setRollbackOnly();
                }

            }
        });
}

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java编程事务是一种在Java应用程序中使用编程管理事务的方法。它与声明事务相对,声明事务是通过配置文件或注解来管理事务。 在编程事务中,开发人员需要显地在代码中编写事务管理逻辑。通常,事务管理逻辑包括以下步骤: 1. 获取一个事务管理器(Transaction Manager)实例。 2. 开始一个新的事务。 3. 执行一系列数据库操作或其他需要事务管理的操作。 4. 如果所有操作都成功,则提交事务。 5. 如果出现错误或异常,则回滚事务。 以下是一个基本示例,演示了如何使用编程事务来管理数据库操作: ```java // 获取事务管理器 TransactionManager txManager = new TransactionManager(); // 开始事务 txManager.beginTransaction(); try { // 执行数据库操作,比如插入数据 DatabaseUtil.insertData(...); // 执行其他操作 // 提交事务 txManager.commitTransaction(); } catch (Exception e) { // 出现异常,回滚事务 txManager.rollbackTransaction(); } ``` 在上面的示例中,我们首先获取了一个事务管理器实例,然后开始一个新的事务。在try块中执行数据库操作,如果没有出现异常,则提交事务。如果出现异常,则在catch块中回滚事务。 需要注意的是,在编程事务中,开发人员需要手动处理事务的开始、提交和回滚。这种方相对比较繁琐,但也提供了更大的灵活性和控制力。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值