问题描述1
我们有如下代码
该方法是一个转账的方法,如果当我们在这段代码中故意加上一个错误时会发生什么事情呢?
当执行测试前数据库中的账户信息如下
执行代码后控制台报错(意料之中)
然后查看数据库发现
转账出现问题了,我们第一时间想到的肯定是没有加事务管理,才导致的,但是真的是这样吗?
我们的更新操作和查询操作,都需要事务管理才能进行,不然就会出现事务回滚,但是更新操作和查询操作我们都可以成功执行,这说明我们是存在事务管理的,那为什么还会出现这种情况呢?
这是因为我们每次使用查询更新的方法后,都会创建一个新的和数据库的连接,而每个连接都会创建一个自己的事务
由此我们应该让事务都处于业务层,而不是持久层中,那我们如何进行实现呢?
问题解决方法
获取当前线程的连接的工具类
我们首先需要写一个从当前线程获取连接的工具类
事务管理的工具类
然后我们写我们的事务管理的工具类
先定义一个刚刚我们写的连接的工具类,然后再添加一个该成员变量的set方法用于spring注入
然后写开始事务的方法
然后写提交事务的方法
然后是回滚事务的方法
然后是释放连接的方法
在释放连接的方法中涉及到一个问题,我们getThreadConnection().close()方法只是将连接归还给了连接池,这意味着连接还在,只是无法使用,被我们关闭了。
线程中也有池的概念,叫做线程池,当我们的线程使用完了之后,也会归还给线程池,这时候如果我们获取连接的这个线程使用完了之后,连接归还给了连接池,线程归还给了线程池,但是这个时候线程还绑定着我们的连接的,只不过连接处于关闭状态。也就是说我们在下一次判断当前线程是否有连接的时候,肯定是存在的,但是这个连接使用不了
所以我们需要在获取当前线程的连接的工具类中添加一个解绑的方法
然后我们将连接归还连接池的后面还要进行当前线程和连接的解绑
修改转账方法的代码
然后完善spring的注入,我们查看数据库,
然后执行方法,控制台报错/byzore
然后再次查看数据库
发现数据没有发生变化,这说明完成了事务的管理
问题描述2
观察代码,发现我们的方法和方法之间的依赖性特别强!!!
,那么我们如何解决这样子的问题呢???
这时候我们就需要用到动态代理了
解决问题2
首先我们在最开始编写方法的时候,不使用事务管理器来编写
而且该IAccountService的实现类,中的所有方法只需要正常写就可以,就是和上面一样不加事务管理器的写法,我们只需要使用动态代理,来增强这些方法就可以
这时候就解决了问题2描述的问题了,就算事务管理器中的方法更改了名字,同时我们还有很多地方使用到了事务管理其中更改名字的方法,这时候我们只需要该这个获取代理对象的方法中的名字即可,大大减小了方法之间的依赖性,但是这样子又引出了一个问题,那就是bean.xml
的配置十分的繁琐,为了解决这样的问题我们才引入了Aop