在 Spring 框架中,事务管理是确保操作的一致性和完整性的核心部分。Spring 提供了多种方式来实现事务管理,最常用的是声明式事务管理和编程式事务管理。
1、声明式事务管理
声明式事务管理是通过配置文件或注解来定义事务边界。这种方式的优点是将事务管理与业务逻辑分离,减少了业务代码的复杂度。
使用事务注解
可以使用 @Transactional
注解来标记需要事务管理的方法或类。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class MyService {
@Autowired
private MyRepository myRepository;
@Transactional
public void performTransactionalOperation() {
// 业务逻辑
myRepository.save(new MyEntity());
// 如果这里抛出异常,事务会回滚
if (someCondition) {
throw new RuntimeException("执行失败!");
}
}
}
@Transactional 主要属性
(1)propagation
: 定义事务的传播行为,例如:
REQUIRED
(默认):如果存在事务,则加入该事务;否则,创建一个新的事务。REQUIRES_NEW
:总是创建一个新事务,挂起当前事务(如果存在)。
(2)isolation
: 定义事务的隔离级别,例如:
DEFAULT
:使用数据库的默认隔离级别。READ_COMMITTED
:确保一个事务只能读取已经提交的数据。SERIALIZABLE
:最高的隔离级别,确保事务串行执行。
(3)timeout
: 指定事务的超时时间(秒),超过此时间事务将被回滚。
(4)readOnly
: 指定事务是否只读,这可以帮助数据库优化查询操作。
(5)rollbackFor
: 指定哪些异常会导致事务回滚。可以设置为多个异常类型。
(6)noRollbackFor
: 指定哪些异常不会导致事务回滚。可以设置为多个异常类型。
事务传播行为
REQUIRED
: 当前存在事务,加入事务;否则,创建新事务。REQUIRES_NEW
: 创建新事务,暂停当前事务。NESTED
: 在当前事务内嵌套事务。支持保存点回滚。SUPPORTS
: 支持当前事务,如果没有事务则非事务执行。NOT_SUPPORTED
: 以非事务方式执行,挂起当前事务。NEVER
: 以非事务方式执行,如果有事务则抛出异常。
事务隔离级别
DEFAULT
: 默认隔离级别。READ_UNCOMMITTED
: 允许读取未提交的数据(最低隔离级别)。READ_COMMITTED
: 只允许读取已提交的数据。REPEATABLE_READ
: 保证相同事务中多次读取同一数据返回相同结果。SERIALIZABLE
: 最高隔离级别,事务完全串行化执行。
2、编程式事务管理
编程式事务管理在代码中显式地控制事务边界。这种方式的灵活性更高,但代码的复杂度也较高。
编写代码使用事务(无返回值)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
@Service
public class MyService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private TransactionTemplate transactionTemplate;
public void performTransactionalOperation() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
jdbcTemplate.update("INSERT INTO my_table (column) VALUES (?)", value);
// 如果这里抛出异常,事务会回滚
if (someCondition) {
throw new RuntimeException("Something went wrong!");
}
} catch (Exception e) {
status.setRollbackOnly(); // 标记事务为回滚
throw e;
}
}
});
}
}
编写代码使用事务(有返回值,内部类实现)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.transaction.TransactionCallback;
import org.springframework.transaction.TransactionStatus;
@Service
public class MyService {
private final TransactionTemplate transactionTemplate;
@Autowired
public MyService(PlatformTransactionManager transactionManager) {
this.transactionTemplate = new TransactionTemplate(transactionManager);
}
public String performTransaction() {
return transactionTemplate.execute(new TransactionCallback<String>() {
@Override
public String doInTransaction(TransactionStatus status) {
try {
//业务(更新、新增)
return "Transaction successful";
} catch (Exception e) {
//事务回滚
status.setRollbackOnly();
return "Transaction failed: " + e.getMessage();
}
}
});
}
}
编写代码使用事务(有返回值,Lambda 表达式实现)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
@Service
public class MyService {
private final TransactionTemplate transactionTemplate;
@Autowired
public MyService(PlatformTransactionManager transactionManager) {
this.transactionTemplate = new TransactionTemplate(transactionManager);
}
public String performTransaction() {
return transactionTemplate.execute(status -> {
try {
//业务(更新、新增)
return "Transaction successful";
} catch (Exception e) {
//事务回滚
status.setRollbackOnly();
return "Transaction failed: " + e.getMessage();
}
});
}
}
编写代码使用事务(设置保存点)
- 使用
DefaultTransactionStatus
的createSavepoint()
方法来创建保存点。 - 使用
rollbackToSavepoint(savepoint)
方法将事务回滚到指定的保存点。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
@Service
public class MyService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private TransactionTemplate transactionTemplate;
public void performTransactionalOperation() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
jdbcTemplate.update("INSERT INTO my_table (column) VALUES (?)", value);
//设置保存点
Object savepoint = status.createSavepoint();
jdbcTemplate.update("INSERT INTO my_table (column1) VALUES (?)", value);
} catch (Exception e) {
//回滚到保存点
status.rollbackToSavepoint(savepoint);
throw e;
}
}
});
}
}
3、总结
- 声明式事务管理 使用注解或 XML 配置,将事务管理的关注点从业务逻辑中分离出来,更加简洁易用。
- 编程式事务管理 允许在代码中显式地控制事务边界,适用于需要动态控制事务的场景,但增加了代码的复杂性。