5.2 声明式事务管
Spring的事务管理可以通过两种方式来实现,一种是基于XML的方式,另一种是基于Annotation的方式。
5.2.1 基于XML方式的声明式事务
- 在Eclipse中,创建一个名为test1008的Web项目,在项目的lib目录下导入chapter04项目中的所有JAR包,并将AOP所需JAR包也导入到lib目录中。导入后的lib目录如图所示:
2、将chapter04项目中的代码和配置文件复制到test1008项目的src目录下,并在AccountDao接口中,创建一个转账的方法transfer(),其代码如下所示:
3、在其实现类AccountDaoImpl中实现transfer()方法,编辑后的代码如下所示:
在上述代码中,使用了两个update()方法对account表中的数据执行首款和汇款的更新操作。在这两个操作之间,添加了一行代码“int i=1/0;”来模拟系统运行时的突发性问题。如果没有事务控制,那么在转账操作执行之后,收款用户的余额会增加,而汇款用户的余额会因为系统出现问题而不变,这显然是有问题的;如果增加了事务控制,那么在转账操作执行之后,收款用户的余额和汇款用户的余额在问题出现前后都应该保持不变。
4、修改配置文件applicationContext.xml,添加命名空间并编辑事务管理的相关配置代码,如图所示:
在该文件中,首先启用了Spring配置文件的aop、tx和context3个命名空间(从配置数据源到声明事务管理器的部分都没有变化),然后定义了id为transactionManager的事务管理器,接下来通过编写的通知来声明事务,最后通过声明AOP的方式让Spring自动生成代理。
5、在com.itheima.jdbc包中,创建测试类TransactionTest,并在类中编写测试方法xmlTest,如图所示:
在该文件中,获取了AccountDao实例后,调用了实例中的转账方法,由Jack向Rose的账户中转入100元。如果在配置文件中所声明的事务代码能够起作用,那么在整个转账方法执行完毕后,Jack和Rose账户余额应该都是原来的值。
在执行操作之前,先查看account表中的数据,如图所示:
从上图中可以看出,此时Jack的账户余额是2000,而Rose的账户余额是500。执行完文件TransactionTest测试方法后,Junit的控制台的显示结果如图所示:
从该图中可以看到,Junit控制台报出了“/by zero”的算术异常信息。此时如果再次查询数据表account:
发现表中Jack和Rose的账户余额并没有发生任何变化,这说明Spring中的事务管理配置已经生效。
5.2.2 基于Annotation方式的声明式事务
(1)在src目录下,创建一个Spring的配置文件applicationContext-annotation.xml,在该文件中声明事务管理器等配置信息,如图所示:
与基于XML方式的配置文件相比,此文件通过注册事务管理驱动器,这样大大减少了配置文件中的代码量。
(2)在AccountDaoImpl类的transfer()方法上添加事务注解,添加后的代码如下所示:
上述方法已经添加了@Transactional()注解,并且使用注解的参数配置了事务详情,各个参数之间要用英文逗号“,”进行分隔。
(3)在TransactionTest类中,创建测试方法annotationTest(),编辑后的代码如下所示:
从上述代码可以看出,与XML方式的测试方法相比,该方法只是对配置文件的名称进行了修改。程序执行后,会出现与XML方式同样的执行结果。
从该图中可以看到,Junit控制台报出了“/by zero”的算术异常信息。
此时再次查询数据表account:
发现表中Jack和Rose的账户余额并没有发生任何变化,这说明Spring中的事务管理配置已经生效。