事务-@transactional注解

什么是事务

事务是一组操作单元,是一个不可分割的工作单位,要么都执行,要么都不执行。保证数据的一致性和完整性。

事务的特性

事务具有四个特性:ACID

  • 原子性(Atomicity):事务是一个不可分割的工作单位,要么都执行,要么都不执行。
  • 一致性(Consistency):事务执行前后,数据的完整性保持一致。
  • 隔离性(Isolation):多个事务之间互不干扰。
  • 持久性(Durability):事务执行成功后,数据的修改是永久的。

@Transactional注解

@Transactional注解用于声明一个方法需要事务支持,Spring会为这个方法创建一个事务代理,当方法执行时,如果抛出异常,则事务会回滚,否则事务会提交。

@Transactional注解的属性

  • rollbackFor:哪些异常会导致事务回滚,默认值是RuntimeException
  • propagation:事务的传播行为,默认值是REQUIRED

rollbackFor属性

rollbackFor属性的默认值是RuntimeException,所以默认情况下,只有RuntimeException及其子类会导致事务回滚,其他异常不会导致事务回滚。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
@Transactional
public void deleteDepartment(Long id) throws Exception {
// 删除部门
departmentMapper.deleteById(id);

if (true) {
throw new Exception("删除员工失败");
}

// 删除部门下的员工
employeeMapper.deleteByDepartmentId(id);
}

此时,删除部门成功,但是删除员工失败,因为删除员工失败抛出的是Exception异常,而Exception不是RuntimeException的子类,所以不会导臿事务回滚,导致部门删除成功,员工删除失败。

如果想让删除员工失败时也回滚事务,可以将rollbackFor属性设置为Exception:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteDepartment(Long id) throws Exception {
// 删除部门
departmentMapper.deleteById(id);

if (true) {
throw new Exception("删除员工失败");
}

// 删除部门下的员工
employeeMapper.deleteByDepartmentId(id);
}

这样,删除员工失败时会导致事务回滚,部门也不会删除。

propagation属性

propagation属性用于设置事务的传播行为,有以下几种取值:

  • REQUIRED:如果当前没有事务,则创建一个新事务,如果当前有事务,则加入当前事务。
  • REQUIRES_NEW:需要新事务,无论当前是否有事务,都会创建一个新事务。
  • SUPPORTS:如果当前有事务,则加入当前事务,如果当前没有事务,则以非事务的方式执行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void log(String message) {
logMapper.insert(message);
}

@Override
@Transactional(propagation = Propagation.REQUIRED)
public void deleteDepartment(Long id) {
try {
// 删除部门
departmentMapper.deleteById(id);

int i = 1 / 0; // 抛出异常

// 删除部门下的员工
employeeMapper.deleteByDepartmentId(id);
} finally {
// 记录日志
log("删除部门:" + id);
}
}

以上代码需求为:无论是否删除部门成功,都要记录日志,如果删除部门失败,日志也要记录,所以需要使用REQUIRES_NEW传播行为,这样无论删除部门是否成功,都会记录日志。