文章目录
- TransactionDefinition 接口:
- TransactionStatus 接口
- PlatformTransactionManager接口
- 基于 @Transactional 的声明式事务管理
- @Transactional声明式事务的例子
认识事务
- 以可控的方式对数据资源进行访问的一组操作称为事务;在事务执行前后,数据资源所承载的系统状态始终处于正确的状态。
- 事务特性(ACID)
- 原子性(Atomicity):事务包括的全部操作是一个整体,象原子一样不可分割。这些操作要么全部提交成功,但只要其中一个操作失败,则全部失败。
- 一致性(Consistency):保证事务开始和结束之间的中间状态不会被其他事务看到。
- 隔离性(Isolation):适当的破坏一致性来提升性能与并行度 。
- 持久性(Durability):每一次的事务提交后就会保证不会丢失。
- Read Uncommitted(读取未提交内容)
- Read Committed(读取提交内容)
- Repeatable Read(可重读)
- Serializable(可串行化)
Spring事务架构
- PlatformTransactionManager事务管理器。
- TransactionDefinition事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则)。
- TransactionStatus事务运行状态。
TransactionDefinition 接口:
- 当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。Spring定义了七种传播行为:
定义 | 说明 |
PROPAGATION_REQUIRED | 如果当前没有事务,就新建一个事务,如果已经存在一个事务,则加入到这个事务中。这是最常见的选择。 |
PROPAGATION_SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
PROPAGATION_MANDATORY | 表示该方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常。 |
PROPAGATION_REQUIRED_NEW | 表示当前方法必须运行在它自己的事务中。一个新的事务将被启动。如果存在当前事务,在该方法执行期间,当前事务会被挂起。 |
PROPAGATION_NOT_SUPPORTED | 表示该方法不应该运行在事务中。如果当前存在事务,就把当前事务挂起。 |
PROPAGATION_NEVER | 表示当前方法不应该运行在事务上下文中。如果当前正有一个事务在运行,则会抛出异常。 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 |
TransactionStatus 接口
- 在事务处理过程中,我们可以使用TransactionStatus 接口进行如下工作:
- 查询事务状态;
- 通过setRollbackOnly方法标记当前事务以使其回滚;
- 创建内部嵌套事务。
PlatformTransactionManager接口
- Spring的事务抽象框架以PlatformTransactionManager作为顶层抽象接口,具体的实现交给不同的实现类,使用对象可以根据当前场景,选择使用或者替换哪一个具体的实现类。
Spring 声明式事务管理
- 随着SpringBoot的诞生与推广,基于注解的声明式事务管理已经得到了广泛使用。声明式事务管理是建立在 Spring AOP
基于 @Transactional 的声明式事务管理
- 配置文件开启注解驱动,在相关的类和方法上通过注解@Transactional标识。
- Spring 在启动的时候会去解析生成相关的bean,这时候会查看拥有相关注解的类和方法,并且为这些类和方法生成代理,并根据@Transaction的相关参数进行相关配置注入。
- 真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。
属性名 | 说明 |
name | 当在配置文件中有多个 TransactionManager , 可以用该属性指定选择哪个事务管理器。 |
propagation | 事务的传播行为,默认值为 REQUIRED。 |
isolation | 事务的隔离度,默认值采用 DEFAULT。 |
timeout | 事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务。 |
read-only | 指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。 |
@Transactional声明式事务的例子
/**
* 基于 @Transactional 的声明式事务管理
*/
@Service
public class UserService {
// Spring Data JPA
@Autowired
private UserRepository userRepository;
// Mybatis
@Autowired
private UserMapper userMapper;
// DAO
@Autowired
private UserDAOImpl userDAO;
// 返回所有的用户
@Transactional(readOnly = true,timeout = 20)
public List<User> listUsers() {
return (List<User>) userRepository.findAll();
}
// 保存用户
@Transactional(rollbackFor = Exception.class)
public User saveUser(User user) {
userDAO.addUser(user);
if (user.getName().contains("admin")) {
throw new RuntimeException("名称中不能含有admin");
}
return user;
}
// 删除用户
@Transactional
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
// 查找用户
@Transactional(readOnly = true)
public User findUser(Long id) {
return userRepository.findById(id).get();
}
// 根据名称查找用户--Mybatis
@Transactional(readOnly = true)
public List<User> searchUser(String name) {
return userMapper.findByName(name);
}
}