Spring是如何管理事务的
在 Spring 中,事务管理是通过 PlatformTransactionManager
接口实现的。Spring 提供了两种方式来管理事务:声明式事务管理和编程式事务管理。
1. 声明式事务管理
Spring 推荐使用声明式事务管理,通过 AOP(面向切面编程)来控制事务的边界。声明式事务的核心是 @Transactional
注解,它可以应用于类或方法级别,表示方法执行时需要支持事务。
基本步骤:
- 配置数据源:首先,配置数据源和事务管理器。
- 使用
@Transactional
注解:在方法或类上使用@Transactional
注解,Spring 会自动为其创建事务。
示例代码:
假设我们有一个简单的服务 UserService
,需要在 addUser
方法中添加事务管理。
1. 配置 Spring 事务管理器(XML 配置)
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource">
<!-- 配置数据源 -->
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="transactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="target" ref="userService"/>
</bean>
2. 定义服务类(使用 @Transactional
注解)
import org.springframework.transaction.annotation.Transactional;
public class UserService {
@Transactional
public void addUser(User user) {
// 假设我们在这里进行数据库操作
userDao.save(user);
// 如果存在错误,会回滚事务
}
@Transactional
public void updateUser(User user) {
// 更新用户
userDao.update(user);
}
}
3. 配置 @EnableTransactionManagement
(Java 配置)
如果使用 Java 配置方式,可以通过 @EnableTransactionManagement
启用 Spring 的事务管理功能。
@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = "com.example")
public class AppConfig {
@Bean
public DataSource dataSource() {
// 配置数据源
}
//事务管理器
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
2. 编程式事务管理
编程式事务管理通过直接调用 PlatformTransactionManager
接口来实现事务的开始、提交和回滚。这种方式相对灵活,但不如声明式事务简洁。
示例代码:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
public class UserService {
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private UserDao userDao;
public void addUser(User user) {
// 开始事务
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = transactionManager.getTransaction(def);
try {
// 执行数据库操作
userDao.save(user);
// 提交事务
transactionManager.commit(status);
} catch (Exception e) {
// 回滚事务
transactionManager.rollback(status);
throw new RuntimeException("Error occurred while adding user", e);
}
}
}
3. 事务的传播行为(Propagation)
Spring 提供了多种事务传播行为,决定了事务在方法调用时如何与外部事务互动。常见的传播行为有:
PROPAGATION_REQUIRED
:如果当前存在事务,加入该事务;如果当前没有事务,则创建一个新的事务。PROPAGATION_SUPPORTS
:如果当前存在事务,加入该事务;如果当前没有事务,则以非事务方式执行。PROPAGATION_MANDATORY
:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。PROPAGATION_REQUIRES_NEW
:创建一个新的事务,并暂停当前事务。
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateUser(User user) {
userDao.update(user);
}
4. 事务的隔离级别(Isolation)
事务的隔离级别定义了事务之间的可见性和锁的策略。常见的隔离级别有:
ISOLATION_READ_UNCOMMITTED
:允许读取未提交的数据(最低的隔离级别,容易产生脏读)。ISOLATION_READ_COMMITTED
:只允许读取已提交的数据(防止脏读)。ISOLATION_REPEATABLE_READ
:确保在事务内读取的数据一致(防止不可重复读)。ISOLATION_SERIALIZABLE
:完全串行化的隔离级别,最强的隔离级别(会导致较低的并发性)。
@Transactional(isolation = Isolation.SERIALIZABLE)
public void updateUser(User user) {
userDao.update(user);
}
5. 事务的回滚规则(Rollback)
在 Spring 中,事务默认只会对运行时异常(RuntimeException
)和错误(Error
)进行回滚。如果你希望对其他类型的异常进行回滚,可以在 @Transactional
注解中指定 rollbackFor
属性。
@Transactional(rollbackFor = Exception.class)
public void addUser(User user) throws Exception {
// 如果抛出 Exception 类型的异常,也会回滚事务
userDao.save(user);
}
总结:
Spring 的事务管理机制主要通过声明式事务管理和编程式事务管理两种方式实现:
- 声明式事务使用
@Transactional
注解,通过 AOP 实现事务的管理,简洁易用。 - 编程式事务通过直接操作
PlatformTransactionManager
来实现事务的开始、提交和回滚,更加灵活,但代码较为冗长。
在 Spring 中,事务的管理包括传播行为、隔离级别和回滚规则等内容,可以根据需求灵活配置。