Spring框架的详细介绍( 七 )

如果不考虑隔离性会引发安全性问题:

  • 读问题: 脏读:一个事务读到另一个事务未提交的数据 不可重复读:一个事务读到另一个事务已经提交的 update 数据,导致一个事务中多次查询结果不一致 幻读:一个事务读到另一个事务已经提交的 insert 数据,导致一个事务中多次查询结果不一致
  • 写问题: 丢失更新
解决读问题:设置事务隔离级别
  • Read uncommitted: 未提交读,无法解决任何读问题
  • Read committed: 已提交读,解决脏读问题
  • Repeatable read: 重复读,解决脏读和不可重复读问题
  • Serializable:序列化,解决所有读问题
事务管理API
  1. PlatformTransactionManager: 平台事务管理器
这是一个接口,拥有多个不同的实现类,如 DataSourceTransactionManager 底层使用了JDBC 管理事务; HibernateTransactionManager 底层使用了 Hibernate 管理事务 。
  1. TransactionDefinition: 事务定义信息
用于定义事务的相关信息,如隔离级别、超时信息、传播行为、是否只读等
  1. TransactionStatus: 事务的状态
用于记录在事务管理过程中,事务的状态的对象 。
上述API的关系: Spring 在进行事务管理的时候,首先平台事务管理器根据事务定义信息进行事务管理,在事务管理过程当中,产生各种此状态,将这些状态信息记录到事务状态的对象当中 。
事务的传播行为事务的传播行为主要解决业务层(Service)方法相互调用的问题,也就是不同的业务中存在不同的事务时,如何操作 。
Spring 中提供了7种事务的传播行为,分为三类:
  • 保证多个操作在同一个事务中 PROPAGATION_REQUIRED: B方法调用A方法,如果A中有事务,使用A中的事务并将B中的操作包含到该事务中;否则新建一个事务,将A和B中的操作包含进来 。(默认) PROPAGATION_SUPPORTS:如果A中有事务,使用A的事务;否则不使用事务 PROPAGATION_MANDATORY:如果A中有事务,使用A的事务;否则抛出异常
  • 保证多个操作不在同一个事务中 PROPAGATION_REQUIRES_NEW:如果A中有事务,将其挂起,创建新事务,只包含自身操作 。否则,新建一个事务,只包含自身操作 。PROPAGATION_NOT_SUPPORTED:如果A中有事务,挂起,不使用事务 。PROPAGATION_NEVER:如果A中有事务,抛出异常,也即不能用事务运行 。
  • 嵌套事务 PROPAGATION_NESTED:如果A有事务,按照A的事务执行,执行完成后,设置一个保存点,然后执行B的操作 。如果出现异常,可以回滚到最初状态或保存点状态 。
实例以转账为例,业务层的DAO层类如下:
public interface AccountDao {
public void outMoney(String from,Double money);
public void inMoney(String to,Double money);
}
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{
@Override
public void outMoney(String from, Double money) {
this.getJdbcTemplate().update("update account set money = money - ? where name = ?",money,from);
}
@Override
public void inMoney(String to, Double money) {
this.getJdbcTemplate().update("update account set money = money + ? where name = ?",money,to);
}
}
public interface AccountService {
public void transfer(String from,String to,Double money);
}
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(String from, String to, Double money) {
accountDao.outMoney(from, money);
accountDao.inMoney(to, money);
}
}
在xml中进行类的配置:
<bean id="accountService" class="tx.demo.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<bean id="accountDao" class="tx.demo.AccountDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
事务管理1: 编程式事务管理
  1. 配置平台事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
  1. 配置事务管理模板类
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>


推荐阅读