spring事务实现方式

以下是 Spring 事务管理的代码实现方式,涵盖 编程式事务 和 声明式事务 两种核心方式。


一、编程式事务管理

通过代码手动控制事务的提交和回滚,灵活但代码侵入性高。

1. 使用 TransactionTemplate

TransactionTemplate 是 Spring 提供的简化事务操作的工具类,适合单方法事务场景。

import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.transaction.TransactionStatus;

@Service
public class UserService {
    private final TransactionTemplate transactionTemplate;
    private final UserRepository userRepository;

    //构造器注入,其他方式也可以
    public UserService(TransactionTemplate transactionTemplate, UserRepository userRepository) {
        this.transactionTemplate = transactionTemplate;
        this.userRepository = userRepository;
    }

    public void createUser(User user) {
        // 通过 execute() 方法执行事务逻辑
        transactionTemplate.execute(status -> {
            try {
                userRepository.save(user);
                // 其他数据库操作(如更新关联表)
                return "Success"; // 事务提交
            } catch (Exception e) {
                status.setRollbackOnly(); // 标记事务回滚
                return "Failed: " + e.getMessage();
            }
        });
    }
}

配置 TransactionTemplate

@Configuration
public class TransactionConfig {
    @Bean
    public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) {
        TransactionTemplate template = new TransactionTemplate();
        template.setTransactionManager(transactionManager);
        // 可选:设置事务属性(传播行为、隔离级别等)
        template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        template.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        return template;
    }
}
2. 使用 PlatformTransactionManager

直接通过事务管理器控制事务,适合复杂事务逻辑(如多步骤操作)。

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

@Service
public class OrderService {
    @Autowired
    private PlatformTransactionManager transactionManager;
    @Autowired
    private OrderRepository orderRepository;

    public void placeOrder(Order order) {
        // 定义事务属性(传播行为、隔离级别等)
        TransactionDefinition definition = new DefaultTransactionDefinition();
        definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        // 获取事务状态
        TransactionStatus status = transactionManager.getTransaction(definition);
        
        try {
            orderRepository.save(order);
            // 模拟其他业务操作(如扣减库存)
            inventoryService.deductStock(order.getItemId(), order.getQuantity());
            transactionManager.commit(status); // 提交事务
        } catch (Exception e) {
            transactionManager.rollback(status); // 回滚事务
            throw new RuntimeException("Transaction failed", e);
        }
    }
}

二、声明式事务管理(推荐)

通过注解或 XML 配置声明事务规则,代码侵入性低,由 Spring AOP 代理实现。

1. 使用 @Transactional 注解

在方法或类上添加 @Transactional,由 Spring 自动管理事务生命周期。

启用事务管理(Spring Boot 自动配置,无需手动配置):

@SpringBootApplication
@EnableTransactionManagement // 显式启用(Spring Boot 默认自动启用)
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Service 层使用注解

@Service
public class ProductService {
    private final ProductRepository productRepository;

    public ProductService(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }

    @Transactional(
        propagation = Propagation.REQUIRED, // 默认值:当前有事务则加入,否则新建
        isolation = Isolation.READ_COMMITTED, // 避免脏读
        rollbackFor = Exception.class, // 指定回滚的异常类型
        timeout = 30 // 事务超时时间(秒)
    )
    public void updateProduct(Product product) {
        productRepository.update(product);
        // 其他操作(如记录日志)
        logService.logUpdate(product.getId());
    }

    @Transactional(readOnly = true) // 只读事务(优化性能)
    public Product getProduct(Long id) {
        return productRepository.findById(id);
    }
}
2. 事务传播行为(Propagation)示例

场景:外层方法调用内层方法时,事务如何传递。

@Service
public class AccountService {
    @Autowired
    private UserService userService;

    @Transactional(propagation = Propagation.REQUIRED)
    public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
        userService.deductBalance(fromId, amount); // 调用另一个事务方法
        userService.addBalance(toId, amount);
    }
}

@Service
public class UserService {
    @Transactional(propagation = Propagation.REQUIRED)
    public void deductBalance(Long userId, BigDecimal amount) {
        // 扣减余额
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void addBalance(Long userId, BigDecimal amount) {
        // 独立事务执行(即使外层事务回滚,此操作仍提交)
    }
}
3. 事务隔离级别(Isolation)示例
@Transactional(isolation = Isolation.SERIALIZABLE) // 最高隔离级别(避免幻读)
public void batchUpdateProducts(List<Product> products) {
    products.forEach(product -> productRepository.update(product));
}

三、XML 配置方式(旧项目适用)

通过 XML 定义事务规则,适合非注解项目。

配置事务管理器

<bean id="transactionManager" 
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

<!-- 定义事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="save*" propagation="REQUIRED"/>
        <tx:method name="update*" propagation="REQUIRED"/>
        <tx:method name="get*" read-only="true"/>
        <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
    </tx:attributes>
</tx:advice>

<!-- 定义 AOP 切面 -->
<aop:config>
    <aop:pointcut id="serviceMethods" 
                  expression="execution(* com.example.service.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/>
</aop:config>

四、事务失效的常见场景及解决

1. 自调用问题(同类方法调用)

问题:同一类中方法 A 调用方法 B,即使 B 有 @Transactional,事务也不会生效。

解决

  • 将方法 B 移到另一个类。

  • 使用 AopContext.currentProxy() 获取代理对象:

    @Transactional
    public void methodA() {
        ((UserService) AopContext.currentProxy()).methodB();
    }
    
    @Transactional
    public void methodB() {
        // 事务生效
    }
2. 异常未抛出

问题:默认只回滚 RuntimeException 和 Error,其他异常需显式配置。

解决

@Transactional(rollbackFor = Exception.class) // 所有异常都触发回滚
public void update() throws Exception {
    // ...
}
3. 非 public 方法

问题@Transactional 注解在非 public 方法上无效。

解决:确保方法为 public


总结

  • 编程式事务:通过 TransactionTemplate 或 PlatformTransactionManager 手动控制,适合复杂事务。

  • 声明式事务:使用 @Transactional 注解,简洁高效,推荐大多数场景。

  • 关键配置:传播行为(propagation)、隔离级别(isolation)、回滚规则(rollbackFor)。

  • 常见陷阱:自调用、异常处理、非 public 方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时光呢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值