Spring事务管理之声明式事务管理-基于注解的方式
© 版权声明:本文为博主原创文章,转载请注明出处
案例
- 利用Spring的声明式事务(TransactionProxyFactoryBean)管理模拟转账过程
数据库准备
-- 创建表 CREATE TABLE `account`( `id` INT NOT NULL AUTO_INCREMENT, `name` VARCHAR(100) NOT NULL, `money` DOUBLE DEFAULT 0, PRIMARY KEY (`id`) )ENGINE = INNODB DEFAULT CHARSET = UTF8; -- 初始化数据 INSERT INTO account (name, money) VALUES ('张三', 1000); INSERT INTO account (name, money) VALUES ('李四', 1000); INSERT INTO account (name, money) VALUES ('王五', 1000);
实例
1.项目结构
2.pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.spring</groupId> <artifactId>SpringTransaction-Annotation</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>SpringTransaction-Annotation Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.version>4.3.8.RELEASE</spring.version> </properties> <dependencies> <!-- junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- spring core --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <!-- spring dao --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <!-- spring test --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> <scope>test</scope> </dependency> <!-- MySQL --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.42</version> </dependency> <!-- C3P0 --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.2</version> </dependency> <!-- AspectJ --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.10</version> </dependency> </dependencies> <build> <finalName>SpringTransaction-Annotation</finalName> </build> </project>
3.AccountDao.java
package org.spring.dao; /** * 转账操作DAO层接口 * */ public interface AccountDao { /** * 转出 * * @param out * 转出账户 * @param money * 转出金额 */ void outMoney(String out, double money); /** * 转入 * * @param int * 转入账户 * @param money * 转出金额 */ void inMoney(String in, double money); }
4.AccountDaoImpl.java
package org.spring.dao.impl; import org.spring.dao.AccountDao; import org.springframework.jdbc.core.support.JdbcDaoSupport; /** * 转账操作DAO层实现类 * */ public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao { /** * 转出 */ public void outMoney(String out, double money) { String sql = "update account set money = money - ? where name = ?"; this.getJdbcTemplate().update(sql, money, out); } /** * 转入 */ public void inMoney(String in, double money) { String sql = "update account set money = money + ? where name = ?"; this.getJdbcTemplate().update(sql, money, in); } }
5.AccountService.java
package org.spring.service; /** * 转账操作业务层接口 * */ public interface AccountService { /** * 转账 * * @param out * 转出账户 * @param in * 转入账户 * @param money * 转账金额 */ void transfer(String out, String in, double money); }
6.AccountServiceImpl.java
package org.spring.service.impl; import org.spring.dao.AccountDao; import org.spring.service.AccountService; import org.springframework.transaction.annotation.Transactional; /** * 转账操作业务层实现类 * */ @Transactional public class AccountServiceImpl implements AccountService { private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } /** * 转账 */ public void transfer(String out, String in, double money) { accountDao.outMoney(out, money); accountDao.inMoney(in, money); } }
7.jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.username=root jdbc.password=*** jdbc.url=jdbc:mysql:///spring_transaction?useSSL=true&characterEncoding=UTF-8
8.applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 引入外部属性文件 --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 配置C3P0连接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"/> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <property name="jdbcUrl" value="${jdbc.url}"/> </bean> <!-- 配置业务类 --> <bean id="accountService" class="org.spring.service.impl.AccountServiceImpl"> <!-- 注入DAO --> <property name="accountDao" ref="accountDao"/> </bean> <!-- 配置DAO类 --> <bean id="accountDao" class="org.spring.dao.impl.AccountDaoImpl"> <!-- 注入数据库连接池 --> <property name="dataSource" ref="dataSource"/> </bean> <!-- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 注入数据库连接池 --> <property name="dataSource" ref="dataSource"/> </bean> <!-- 开启注解代理 --> <tx:annotation-driven transaction-manager="transactionManager"/> </beans>
9.TestAnnotationTransaction.java
package org.spring.test; import javax.annotation.Resource; import org.junit.Test; import org.junit.runner.RunWith; import org.spring.service.AccountService; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class TestAnnotationTransaction { @Resource(name="accountService") private AccountService accountService; @Test public void testTransfer() { accountService.transfer("张三", "李四", 200d); } }
10.效果预览
10.1 正常执行
10.2 非正常执行(修改AccountServiceImpl.java如下)
package org.spring.service.impl; import org.spring.dao.AccountDao; import org.spring.service.AccountService; import org.springframework.transaction.annotation.Transactional; /** * 转账操作业务层实现类 * */ @Transactional public class AccountServiceImpl implements AccountService { private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } /** * 转账 */ public void transfer(String out, String in, double money) { accountDao.outMoney(out, money); int i = 1 / 0; accountDao.inMoney(in, money); } }
结果如下:
© 版权声明:本文为博主原创文章,转载请注明出处