Spring事务传播类型

Spring框架提供了声明式事务管理,允许开发者通过配置来控制事务的行为。事务传播行为(Transaction Propagation Behavior)定义了在事务上下文中执行的方法如何与现有的事务关联。Spring定义了以下七种事务传播行为:

源码

/*
 * Copyright 2002-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.transaction.annotation;

import org.springframework.transaction.TransactionDefinition;

/**
 * Enumeration that represents transaction propagation behaviors for use
 * with the {@link Transactional} annotation, corresponding to the
 * {@link TransactionDefinition} interface.
 *
 * @author Colin Sampaleanu
 * @author Juergen Hoeller
 * @since 1.2
 */
public enum Propagation {

    /**
	 * Support a current transaction, create a new one if none exists.
	 * Analogous to EJB transaction attribute of the same name.
	 * <p>This is the default setting of a transaction annotation.
	 */
    REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),

    /**
	 * Support a current transaction, execute non-transactionally if none exists.
	 * Analogous to EJB transaction attribute of the same name.
	 * <p>Note: For transaction managers with transaction synchronization,
	 * {@code SUPPORTS} is slightly different from no transaction at all,
	 * as it defines a transaction scope that synchronization will apply for.
	 * As a consequence, the same resources (JDBC Connection, Hibernate Session, etc)
	 * will be shared for the entire specified scope. Note that this depends on
	 * the actual synchronization configuration of the transaction manager.
	 * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization
	 */
    SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),

    /**
	 * Support a current transaction, throw an exception if none exists.
	 * Analogous to EJB transaction attribute of the same name.
	 */
    MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),

    /**
	 * Create a new transaction, and suspend the current transaction if one exists.
	 * Analogous to the EJB transaction attribute of the same name.
	 * <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
	 * on all transaction managers. This in particular applies to
	 * {@link org.springframework.transaction.jta.JtaTransactionManager},
	 * which requires the {@code javax.transaction.TransactionManager} to be
	 * made available to it (which is server-specific in standard Java EE).
	 * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
	 */
    REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),

    /**
	 * Execute non-transactionally, suspend the current transaction if one exists.
	 * Analogous to EJB transaction attribute of the same name.
	 * <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
	 * on all transaction managers. This in particular applies to
	 * {@link org.springframework.transaction.jta.JtaTransactionManager},
	 * which requires the {@code javax.transaction.TransactionManager} to be
	 * made available to it (which is server-specific in standard Java EE).
	 * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
	 */
	NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),

	/**
	 * Execute non-transactionally, throw an exception if a transaction exists.
	 * Analogous to EJB transaction attribute of the same name.
	 */
	NEVER(TransactionDefinition.PROPAGATION_NEVER),

	/**
	 * Execute within a nested transaction if a current transaction exists,
	 * behave like {@code REQUIRED} otherwise. There is no analogous feature in EJB.
	 * <p>Note: Actual creation of a nested transaction will only work on specific
	 * transaction managers. Out of the box, this only applies to the JDBC
	 * DataSourceTransactionManager. Some JTA providers might support nested
	 * transactions as well.
	 * @see org.springframework.jdbc.datasource.DataSourceTransactionManager
	 */
	NESTED(TransactionDefinition.PROPAGATION_NESTED);


	private final int value;


	Propagation(int value) {
		this.value = value;
	}

	public int value() {
		return this.value;
	}

}

详细说明

REQUIRED

如果当前存在事务,就加入该事务;如果当前没有事务,就新建一个事务。这是默认的事务传播行为。

@Service
public class OrderService {

    @Transactional(propagation = Propagation.REQUIRED)
    public void placeOrder(Order order) {
        // 保存订单
        this.saveOrder(order);
        // 发送通知
        this.sendNotification(order);
    }

    public void saveOrder(Order order) {
        // 模拟数据库操作
    }

    public void sendNotification(Order order) {
        // 模拟发送通知
    }
    
}

placeOrder方法中,由于使用了REQUIRED传播行为,它会加入当前的事务(如果存在)或者新建一个事务。saveOrdersendNotification方法没有声明事务,因此它们会加入placeOrder方法的事务中。

SUPPORTS

如果当前存在事务,就加入该事务;如果当前没有事务,就以非事务方式执行。

@Service
public class MarketingService {

    @Resource
    private EmailService emailService;

    @Transactional(propagation = Propagation.SUPPORTS)
    public void sendMarketingEmails() {
        // 这个方法会在当前事务中执行,如果当前没有事务,则不会创建新事务。
        emailService.sendEmailsToSubscribers();
    }
    
}
@Service
public class SubscriptionService {

    @Resource
    private MarketingService marketingService;

    // 如果当前存在事务,subscribeUser方法将在这个事务中执行。如果当前没有事务,subscribeUser方法将创建一个新的事务。
    @Transactional(propagation = Propagation.REQUIRED)
    public void subscribeUser(User user) {
        // 这个方法会在新的或当前事务中执行。
        subscriptionRepository.save(user);
        // 由于sendMarketingEmails方法的传播行为是SUPPORTS,如果subscribeUser方法在一个事务中执行,sendMarketingEmails方法也会在这个事务中执行;如果subscribeUser方法没有在一个事务中执行,sendMarketingEmails将以非事务方式执行。
        marketingService.sendMarketingEmails();
    }
    
}

MANDATORY

如果当前存在事务,就加入该事务;如果当前没有事务,就抛出异常。

@Service
public class PaymentService {

    @Transactional(propagation = Propagation.MANDATORY)
    public void processPayment(Payment payment) {
        // 这个方法必须在事务中执行,如果当前没有事务,将抛出异常。
        paymentRepository.save(payment);
    }
    
}

@Service
public class OrderService {

    @Resource
    private PaymentService paymentService;

    @Transactional(propagation = Propagation.REQUIRED)
    public void placeOrder(Order order) {
        // 这个方法会在新的或当前事务中执行。
        orderRepository.save(order);
        // 调用PaymentService,它必须在事务中执行。
        paymentService.processPayment(order.getPayment());
    }
}

<font style="color:rgb(6, 6, 7);">PaymentService</font>中,<font style="color:rgb(6, 6, 7);">processPayment</font>方法使用了<font style="color:rgb(6, 6, 7);">MANDATORY</font>传播行为,这意味着它必须在一个事务中执行。如果<font style="color:rgb(6, 6, 7);">placeOrder</font>方法在一个事务中调用<font style="color:rgb(6, 6, 7);">processPayment</font>,那么支付处理将在这个事务中执行。如果没有事务,将抛出异常。

REQUIRES_NEW

总是新建一个事务,如果当前存在事务,就将当前事务挂起。

@Service
public class ProductService {

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateProductDetails(Product product) {
        // 更新产品详情
        this.productRepository.save(product);
        // 发送通知
        this.sendNotification(product);
    }

    public void sendNotification(Product product) {
        // 模拟发送通知
    }
    
}

updateProductDetails方法中,使用了REQUIRES_NEW传播行为,这意味着每次调用这个方法时,都会创建一个新的事务,即使当前存在一个事务也会被挂起。

NOT_SUPPORTED

总是以非事务方式执行,如果当前存在事务,就将当前事务挂起。

@Service
public class ReportingService {

    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void generateReport() {
        // 生成报告,不需要事务
        this.reportRepository.save(report);
    }
    
}

generateReport方法中,使用了NOT_SUPPORTED传播行为,这意味着即使当前存在事务,也会被挂起,这个方法将以非事务方式执行。

NEVER

总是以非事务方式执行,如果当前存在事务,就抛出异常。

@Service
public class ReportingService {

    @Transactional(propagation = Propagation.NEVER)
    public void generateReport() {
        // 这个方法总是以非事务方式执行,如果当前存在事务,将抛出异常。
        reportRepository.save(new Report());
    }
    
}

@Service
public class OrderService {

    @Resource
    private ReportingService reportingService;

    @Transactional(propagation = Propagation.REQUIRED)
    public void processOrder(Order order) {
        // 这个方法会在新的或当前事务中执行。
        orderRepository.save(order);
        // 调用ReportingService,它将以非事务方式执行。
        reportingService.generateReport();
    }
}

<font style="color:rgb(6, 6, 7);">ReportingService</font>中,<font style="color:rgb(6, 6, 7);">generateReport</font>方法使用了<font style="color:rgb(6, 6, 7);">NEVER</font>传播行为,这意味着它总是以非事务方式执行。如果<font style="color:rgb(6, 6, 7);">processOrder</font>方法在一个事务中调用<font style="color:rgb(6, 6, 7);">generateReport</font>,那么生成报告的操作将以非事务方式执行,如果当前存在事务,将抛出异常。

NESTED

如果当前存在事务,就在嵌套事务内执行。如果当前没有事务,就和REQUIRED一样新建一个事务。

@Service
public class UserService {

    @Transactional(propagation = Propagation.REQUIRED)
    public void registerUser(User user) {
        // 注册用户
        this.userRepository.save(user);
        // 触发额外的操作
        this.triggerAdditionalOperations(user);
    }

    @Transactional(propagation = Propagation.NESTED)
    public void triggerAdditionalOperations(User user) {
        // 执行一些需要嵌套事务的操作
        this.additionalRepository.save(user);
    }
    
}

registerUser方法中,使用了REQUIRED传播行为,而在triggerAdditionalOperations方法中使用了NESTED传播行为。这意味着triggerAdditionalOperations方法会在registerUser方法的事务内执行,但它拥有自己的事务上下文,可以独立地进行回滚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

付聪1210

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

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

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

打赏作者

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

抵扣说明:

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

余额充值