一、导包(下面用一个转账的例子来实现):
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>4.12</junit.version>
<c3p0.version>0.9.5.2</c3p0.version>
<mysql.version>5.1.38</mysql.version>
<spring.version>5.0.8.RELEASE</spring.version>
<aspect.version>1.8.10</aspect.version>
</properties>
<dependencies>
<!-- spring的aop支持 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspect.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspect.version}</version>
</dependency>
<!-- spring框架支持 -->
<!-- spring上下文支持 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring-jdbc支持,使用JDBCTemplate -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring整合junit测试 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<!-- mysql connector-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- c3p0支持 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>${c3p0.version}</version>
</dependency>
<!-- junit测试支持 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
二、创建Account实体类
public class Account {
private int id;
private String name;
private double money;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
}
三、创建对应的dao
接口
public interface AccountDao {
//减钱操作
public void reduce(int id,double money);
//加钱操作
public void increase(int id,double money);
}
实现类(我继承的JdbcDaoSupport,可以直接获取JdbcTemplate)
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{
//减钱操作
@Override
public void reduce(int id, double money) {
String sql = "update t_account set money=money-? where id=?";
this.getJdbcTemplate().update(sql, money,id);
}
//加钱操作
@Override
public void increase(int id, double money) {
String sql = "update t_account set money=money+? where id=?";
this.getJdbcTemplate().update(sql, money,id);
}
}
四、创建对应的service
接口
public interface AccountService {
//转账
public void transfer(int id1, int id2, double money);
}
实现类
//@Transactional开启事务管理,在类前面表示整个的所有方法都开启事务管理
@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED,readOnly=false)
public class AccountServiceImpl implements AccountService{
@Resource(name="accountDao")
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(int id1, int id2, double money) {
//先减钱
accountDao.reduce(id1,money);
//增加异常
//int a = 1/0;
//再加钱
accountDao.increase(id2, money);
}
}
五、创建对一个数据库
插入两条测试数据:
六、配置文件(注解事务的配置文件比非注解事务少了很多配置的步骤,<tx:annotation-driven/>开启注解即可
)
<?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"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 读取配置文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- dataSource -->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${dataSource.driverClassName}"/>
<property name="jdbcUrl" value="${dataSource.url}"/>
<property name="user" value="${dataSource.username}"/>
<property name="password" value="${dataSource.password}"/>
</bean>
<!-- dao注入dataSource -->
<bean name="accountDao" class="com.spring_demo.transaction.dao.AccountDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- service注入dao -->
<bean name="accountService" class="com.spring_demo.transaction.service.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<!-- 开启注解 -->
<context:annotation-config/>
<!-- aop事务 -->
<!-- 1.配置事务核心管理器,不同平台不一样-->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 开启注解事务 -->
<tx:annotation-driven/>
</beans>
isolation是隔离级别 propagation是传播行为 ;
七、测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext-transaction.xml")
public class TestTransaction {
@Resource(name="accountService")
private AccountService accountService;
@Test
public void test1() {
//转账50
accountService.transfer(1, 2, 50);
}
}