什么是事务
逻辑上的一组操作,组成这组操作的各个单元,要么全都成功,要么全都失败。
一个Spring事务管理的程序
- 创建AccountDao接口,其中包含一个转账方法
AccountDAO接口
public interface AccountDAO{
public void transfer(String outUser, String inUser, Double money);
}
AccountDAOImpl实现类
public class AccountDAOImpl implements AccountDAO{
@Override
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);
}
}
- 配置Spring配置文件applicationContext.xml文件
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/spring" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="accountDao" class="com.itheima.jdbc.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<bean id="transactionManager" class=
"org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"
isolation="DEFAULT" read-only="false" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut expression="execution(* com.itheima.jdbc.*.*(..))"
id="txPointCut" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut" />
</aop:config>
- 测试:当调用转账方法时,如果发生异常,因为配置了事务管理器,账户余额应该都不变;如果没有配置事务,会发现其中转账一方金额增加,另一个金额不变,这在转账中是不被允许的。
@Test
public void annotationTest(){
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext-annotation.xml");
AccountDao accountDao =
(AccountDao)applicationContext.getBean("accountDao");
accountDao.transfer("Jack", "Rose", 100.0);
System.out.println("转账成功!");
}
基于注解的事务管理
步骤
- 在Spring容器中注册事务注解驱动
<tx:annotation-driven transaction-manager="transactionManager"/>
- 在需要使用事务的Spring Bean类或者Bean类的方法上添加注解@Transactional。在类上对所有方法都有效,在某个方法上,只对该方法有效。
@Transactional注解的参数和描述
| 参数名称 |
描述 |
| value |
指定要使用的事务管理器 |
| transactionManager |
指定事务的限定符值 |
| isolation |
指定事务的隔离级别 |
| noRollbackFor |
特定异常不回滚 |
| noRollbackForClassName |
特定的多个异常不回滚 |
| propagation |
传播行为 |
| read-only |
事务是否只读 |
| rollbackFor |
遇到特定异常强制回滚事务 |
| rollbackForClassName |
遇到多个特定异常强制回滚事务 |
| timeout |
事务超时时长 |
事务的传播行为
一个基于注解的事务例子
- Spring配置事务注解驱动
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/spring" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="accountDao" class="com.itheima.jdbc.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<bean id="transactionManager" class=
"org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
- 在方法上添加注解
public class AccountDaoImpl implements AccountDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Transactional(propagation = Propagation.REQUIRED,
isolation = Isolation.DEFAULT, readOnly = false)
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);
}
}
|