基于XML方式的声明式事务管理是通过在配置文件中配置事务规则的相关声明来实现的。在使用XML文件配置声明式事务管理时,首先要引入tx命名空间,在引入tx命名空间之后,可以使用
配置
| 属性 | 说明 |
| name | 用于指定方法名的匹配模式,该属性为必选属性,它指定了与事务属性相关的方法名。 |
| propagation | 用于指定事务的传播行为。 |
| isolation | 用于指定事务的隔离级别。 |
| read-only | 用于指定事务是否只读。 |
| timeout | 用于指定事务超时时间。 |
| rollback-for | 用于指定触发事务回滚的异常类。 |
| no-rollback-for | 用于指定不触发事务回滚的异常类。 |
接下来通过一个案例演示如何通过XML方式实现Spring的声明式事务管理。本案例以9.2小节的项目代码和数据表为基础,编写一个模拟银行转账的程序,要求在转账时通过Spring对事务进行控制。案例具体实现步骤如下。
在chapter09项目的pom.xml文件中加入aspectjweaver依赖包和aopalliance依赖包作为实现切面所需的依赖包。
-
org.aspectj -
aspectjweaver -
1.9.6 -
runtime -
aopalliance -
aopalliance -
1.0
AccountDao接口中声明转账方法transfer()。
- // 转账
- public void transfer(String outUser,
- String inUser,
- Double money);
AccountDaoImpl实现类中实现AccountDao接口中的transfer()方法。
- // 转账 inUser:收款人; outUser:汇款人; money:收款金额
- public void transfer(String outUser, String inUser, Double money) {
- // 收款时,收款用户的余额=现有余额+所汇金额
- this.jdbcTemplate.update("update account set balance = balance +? "
- + "where username = ?",money, inUser);
- // 模拟系统运行时的突发性问题
- int i = 1/0;
- // 汇款时,汇款用户的余额=现有余额-所汇金额
- this.jdbcTemplate.update("update account set balance = balance-? "
- + "where username = ?",money, outUser);
- }
修改chapter09项目的配置文件applicationContext.xml,添加命名空间等相关配置代码。
- "1.0" encoding="UTF-8"?>
"http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop.xsd">
-
-
"dataSource" class= - "org.springframework.jdbc.datasource.DriverManagerDataSource">
-
-
"driverClassName" value="com.mysql.cj.jdbc.Driver" /> -
-
"url" value="jdbc:mysql://localhost/spring?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai" /> -
-
"username" value="root" /> -
-
"password" value="root" /> -
-
-
"jdbcTemplate" - class="org.springframework.jdbc.core.JdbcTemplate">
-
-
"dataSource" ref="dataSource" /> -
-
-
"accountDao" class="com.itheima.AccountDaoImpl"> -
-
"jdbcTemplate" ref="jdbcTemplate" /> -
-
-
"transactionManager" class= - "org.springframework.jdbc.datasource.DataSourceTransactionManager">
-
"dataSource" ref="dataSource" /> -
-
-
"txAdvice" transaction-manager="transactionManager"> -
-
-
"*" propagation="REQUIRED" - isolation="DEFAULT" read-only="false" />
-
-
-
-
-
-
"execution(* com.itheima.*.*(..))" - id="txPointCut" />
-
-
"txAdvice" pointcut-ref="txPointCut" /> -
创建测试类TransactionTest。
- public class TransactionTest {
- public static void main(String[] args) {
- ApplicationContext applicationContext =
- new ClassPathXmlApplicationContext("applicationContext.xml");
- // 获取AccountDao实例
- AccountDao accountDao =
- (AccountDao)applicationContext.getBean("accountDao");
- // 调用实例中的转账方法
- accountDao.transfer("lisi", "zhangsan", 100.0);
- // 输出提示信息
- System.out.println("转账成功!");}}
在执行转账操作前,也就是在执行第5不操作前,先查看account表中的数据。
- mysql> use spring
- Database changed
- mysql> select * from account;
- +----+----------+---------+
- | id | username | balance |
- +----+----------+---------+
- | 1 | zhangsan | 100 |
- | 3 | lisi | 500 |
- | 4 | wnagwu | 300 |
- +----+----------+---------+
- 3 rows in set (0.00 sec)
在执行第5步后,控制台中报出了“/by zero”的算术异常信息。此时再次查询数据表account。
- mysql> select * from account;
- +----+----------+---------+
- | id | username | balance |
- +----+----------+---------+
- | 1 | zhangsan | 100 |
- | 3 | lisi | 500 |
- | 4 | wnagwu | 300 |
- +----+----------+---------+
- 3 rows in set (0.00 sec)
未使用事物管理的缺陷
由XML方式实现声明式事务管理的案例可知,zhangsan的账户余额增加了100,而lisi的账户确没有任何变化,这样的情况显然是不合理的。这就是没有事务管理,系统无法保证数据的安全性与一致性,下面使用事务管理解决该问题。
在第4步的代码文件中添加事务管理的配置。
"txAdvice" transaction-manager="transactionManager"> -
-
"*" propagation="REQUIRED" - isolation="DEFAULT" read-only="false" />
-
"execution(* com.itheima.*.*(..))" - id="txPointCut" />
-
"txAdvice" pointcut-ref="txPointCut"