在Spring中使用事务时创建一个post提交

use*_*190 24 java spring transactions

由于某些原因,我已经手动执行了事务提交并使用Spring PlatformTransactionManager回滚,我需要做的是设置一个钩子,以便在事务提交后进行事后提交操作.

通过观察:

 void commit(TransactionStatus status) throws TransactionException;
Run Code Online (Sandbox Code Playgroud)

我不知道如何确定一个事务是成功的,除了假设它,所以如果不抛出任何expception.

我可以使用AOP作为一个选项,但是如果使用AOP,可能会使用回调方法呢?

Gro*_*eek 47

你可以通过简单的方式得到你想要的东西,用TransactionSynchronizationManagerTransactionSynchronization

有了TransactionSynchronizationManager,您有静态方法来获取有关当前事务的信息,并且您可以注册一个TransactionSynchronization允许您在调用时自动执行提交后的方法

TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization(){
           void afterCommit(){
                //do what you want to do after commit
           }
})
Run Code Online (Sandbox Code Playgroud)

请注意,TransactionSynchronization基于每个线程(对于基本Web请求通常不是问题).

  • 使用`TransactionSynchronizationAdapter`作为实现单个方法的更简洁方法. (11认同)
  • @Alex 从 Spring 5 开始,“TransactionSynchronization”现在使用“default”作为其方法。所以,不需要使用`TransactionSynchronizationAdapter` (4认同)
  • 我写了一篇关于Spring中事务同步的博客文章,以及如何在提交回调后轻松注册http://azagorneanu.blogspot.com/2013/06/transaction-synchronization-callbacks.html (3认同)

Mic*_*dis 15

感谢Grooveek的回答以及Alex在其下的评论 - 我把它放在这里是因为这些组合的建议提供了一个在网络上很难找到的可靠而简洁的解决方案.

使用Spring 4+.如果@Transactional在成功提交后需要对方法进行回调,只需在方法的开头添加:

@Service
public class OneService {

    @Autowired
    OneDao dao;

    @Transactional
    public void a transactionalMethod() {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter(){
            public void afterCommit(){
                //do stuff right after commit
                System.out.println("commit!!!");

            }
        });
        //do db stuff
        dao.save();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 感谢@Michail的回答.对于事务回滚,此方法使用"afterCompletion(int status)"并检查status == TransactionSynchronization.STATUS_ROLLED_BACK (2认同)

Fra*_*son 11

从 Spring 4.2 开始,可以使用基于注解的配置为提交后事件(或更一般的事务同步事件,例如回滚)定义侦听器。这是基于核心 spring 中的事件处理。使用这种方法测试代码更容易,因为您避免了对 TransactionSynchronizationManager 的直接依赖,它可能不会在单元测试中处于活动状态。您可以轻松测试您的事务服务是否发布了一个事件,以及您的侦听器在您收到一个事件时是否执行了正确的操作。

所以不用多说,这是如何设置它:

在这个例子中,我们假设你有一个Customer实体和一个CustomerRepository(以及与之配套的 ORM)。

首先你需要一个新的事件类型NewCustomerEvent

// NewCustomerEvent.java
// Just a regular pojo for the event
public class NewCustomerEvent {

    public String email;

    // constructor, setters and getters omitted
}
Run Code Online (Sandbox Code Playgroud)

然后使用@TransactionalEventListener. 默认情况下,这将在成功提交后执行,但这可以使用phase参数进行更改:

// NewCustomerEventListener.java
@Component
public class NewCustomerEventListener {

    @TransactionalEventListener
    public void handleNewCustomerEvent(NewCustomerEvent newCustomerEvent) {
        // handle new customer event
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,您使用一个ApplicationEventPublisher在发送完所有交易语句后调用 publish 的方法来扩充您的交易服务。

// CustomerRespositoryService.java
@Service
public class CustomerRepositoryService {

    @Inject
    private ApplicationEventPublisher applicationEventPublisher;

    @Inject
    private CustomerRepository customerRepository;

    @Transactional
    public void createCustomer(String email) {
        Customer customer = new Customer(email);
        customerRespotory.save(customer);
        applicationEventPublisher.publish(new NewCustomerEvent(email));
    }

}
Run Code Online (Sandbox Code Playgroud)

也可以看看: