管理事务的方式
- 编程式事务,在代码中编码
- 声明式事务,在配置文件中配置
- 基于xml的声明式事务
- 基于注解的声明式事务
spring 事务的隔离级别与传播级别
TransactionDefinition 接⼝中定义了五个表示隔离级别的常量
- TransactionDefinition.ISOLATION_DEFAULT: 使⽤后端数据库默认的隔离级别,Mysql 默认采⽤的 REPEATABLE_READ隔离级别 Oracle 默认采⽤的 READ_COMMITTED隔离级 别.
- TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔离级别,允许读取 尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
- TransactionDefinition.ISOLATION_READ_COMMITTED: 允许读取并发事务已经提交的 数据,可以阻⽌脏读,但是幻读或不可重复读仍有可能发⽣
- TransactionDefinition.ISOLATION_REPEATABLE_READ: 对同⼀字段的多次读取结果 都是⼀致的,除⾮数据是被本身事务⾃⼰所修改,可以阻⽌脏读和不可重复读,但幻读仍有 可能发⽣。
- TransactionDefinition.ISOLATION_SERIALIZABLE: 最⾼的隔离级别,完全服从ACID的 隔离级别。所有的事务依次逐个执⾏,这样事务之间就完全不可能产⽣⼲扰,也就是说,该 级别可以防⽌脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不 会⽤到该级别。
事务中传播行为
⽀持当前事务的情况:
- TransactionDefinition.PROPAGATION_REQUIRED: 如果当前存在事务,则加⼊该事 务;如果当前没有事务,则创建⼀个新的事务。
- TransactionDefinition.PROPAGATION_SUPPORTS: 如果当前存在事务,则加⼊该事 务;如果当前没有事务,则以⾮事务的⽅式继续运⾏。
- TransactionDefinition.PROPAGATION_MANDATORY: 如果当前存在事务,则加⼊该事 务;如果当前没有事务,则抛出异常。(mandatory:强制性)
不⽀持当前事务的情况:
- TransactionDefinition.PROPAGATION_REQUIRES_NEW: 创建⼀个新的事务,如果当 前存在事务,则把当前事务挂起。
- TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以⾮事务⽅式运⾏,如果 当前存在事务,则把当前事务挂起。
- TransactionDefinition.PROPAGATION_NEVER: 以⾮事务⽅式运⾏,如果当前存在事 务,则抛出异常
其他情况:
TransactionDefinition.PROPAGATION_NESTED: 如果当前存在事务,则创建⼀个事务 作为当前事务的嵌套事务来运⾏;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED
import com.wpw.group.springstudy.sql.User;
import com.wpw.group.springstudy.sql.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class TransactionService {
@Autowired
private UserMapper userMapper;
//由于 @Transactional 采用的是代理模式,采用this调用不会生效,所以这里通过自引用的方式来调用。
@Autowired
private TransactionService transactionService;
/**
* 由于远程调用的是 方法是读未提交的,所以会返回数据
* @return
*/
@Transactional
public User readUncommitIsolation() {
User user = new User();
user.setName("name");
user.setSex("sex");
userMapper.insertSelective(user);
return transactionService.getReadUncommit(user.getId());
}
/**
* 采用的是读未提交隔离级别,调用这个方法的会读取到未提交的事务
* @param id
* @return
*/
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_UNCOMMITTED)
public User getReadUncommit(Long id) {
return userMapper.selectByPrimaryKey(id);
}
/**
* 远程调用的是 默认隔离级别的方法,即可重复读,因此此处会返回null
* @return
*/
@Transactional
public User defaultIsolation() {
User user = new User();
user.setName("name");
user.setSex("sex");
userMapper.insertSelective(user);
return transactionService.getDefault(user.getId());
}
/**
* 未配置隔离级别,会使用默认隔离级别,即数据库默认的事务隔离级别,mysql的默认的隔离级别是 可重复读,所以调用这个方法不会返回数据
* @param id
* @return
*/
@Transactional(propagation = Propagation.REQUIRES_NEW)
public User getDefault(Long id) {
return userMapper.selectByPrimaryKey(id);
}
}