分析事务问题并编写CounnectionUtils

本文探讨了在Java代码中遇到的转账事务问题,解释了由于每个数据库操作新建连接导致的事务失效。解决方案是通过业务层的事务管理,实现连接复用和事务控制。此外,还介绍了如何利用动态代理降低方法间的依赖性,以简化代码并减少配置的复杂性。
摘要由CSDN通过智能技术生成

问题描述1

我们有如下代码
在这里插入图片描述
该方法是一个转账的方法,如果当我们在这段代码中故意加上一个错误时会发生什么事情呢?
在这里插入图片描述
当执行测试前数据库中的账户信息如下
在这里插入图片描述
执行代码后控制台报错(意料之中)
在这里插入图片描述
然后查看数据库发现
在这里插入图片描述
转账出现问题了,我们第一时间想到的肯定是没有加事务管理,才导致的,但是真的是这样吗?
我们的更新操作和查询操作,都需要事务管理才能进行,不然就会出现事务回滚,但是更新操作和查询操作我们都可以成功执行,这说明我们是存在事务管理的,那为什么还会出现这种情况呢?
这是因为我们每次使用查询更新的方法后,都会创建一个新的和数据库的连接,而每个连接都会创建一个自己的事务
在这里插入图片描述
由此我们应该让事务都处于业务层,而不是持久层中,那我们如何进行实现呢?

问题解决方法

获取当前线程的连接的工具类

我们首先需要写一个从当前线程获取连接的工具类
在这里插入图片描述

事务管理的工具类

然后我们写我们的事务管理的工具类
先定义一个刚刚我们写的连接的工具类,然后再添加一个该成员变量的set方法用于spring注入
在这里插入图片描述
然后写开始事务的方法
在这里插入图片描述

然后写提交事务的方法
在这里插入图片描述
然后是回滚事务的方法
在这里插入图片描述
然后是释放连接的方法

在释放连接的方法中涉及到一个问题,我们getThreadConnection().close()方法只是将连接归还给了连接池,这意味着连接还在,只是无法使用,被我们关闭了。
线程中也有池的概念,叫做线程池,当我们的线程使用完了之后,也会归还给线程池,这时候如果我们获取连接的这个线程使用完了之后,连接归还给了连接池,线程归还给了线程池,但是这个时候线程还绑定着我们的连接的,只不过连接处于关闭状态。也就是说我们在下一次判断当前线程是否有连接的时候,肯定是存在的,但是这个连接使用不了在这里插入图片描述

所以我们需要在获取当前线程的连接的工具类中添加一个解绑的方法
在这里插入图片描述
然后我们将连接归还连接池的后面还要进行当前线程和连接的解绑
在这里插入图片描述

修改转账方法的代码

在这里插入图片描述
然后完善spring的注入,我们查看数据库,
在这里插入图片描述
然后执行方法,控制台报错/byzore
在这里插入图片描述
然后再次查看数据库
在这里插入图片描述
发现数据没有发生变化,这说明完成了事务的管理

问题描述2

观察代码,发现我们的方法和方法之间的依赖性特别强!!!
在这里插入图片描述
,那么我们如何解决这样子的问题呢???

这时候我们就需要用到动态代理了

解决问题2

首先我们在最开始编写方法的时候,不使用事务管理器来编写
在这里插入图片描述
而且该IAccountService的实现类,中的所有方法只需要正常写就可以,就是和上面一样不加事务管理器的写法,我们只需要使用动态代理,来增强这些方法就可以
在这里插入图片描述
这时候就解决了问题2描述的问题了,就算事务管理器中的方法更改了名字,同时我们还有很多地方使用到了事务管理其中更改名字的方法,这时候我们只需要该这个获取代理对象的方法中的名字即可,大大减小了方法之间的依赖性,但是这样子又引出了一个问题,那就是bean.xml
的配置十分的繁琐,为了解决这样的问题我们才引入了Aop

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值