在Spring中使用transaction时创建post commit

tct7dpnv  于 2023-09-29  发布在  Spring
关注(0)|答案(4)|浏览(125)

由于某些原因,我已经使用Spring PlatformTransactionManager手动执行了transaction commit和rollback,我需要做的是设置一个钩子,以便在transaction提交后执行post commit操作。
通过查看:

void commit(TransactionStatus status) throws TransactionException;

我不知道我如何确定一个事务是成功的,除非假设它是这样的,如果没有抛出expception。
我可以使用AOP作为一种选择,但是用编程的方式来做呢,也许使用回调方法?

xurqigkl

xurqigkl1#

您可以通过一种更简单的方法得到您想要的东西,使用TransactionSynchronizationManagerTransactionSynchronization
使用TransactionSynchronizationManager,您可以使用静态方法来获取有关当前事务的信息,并且可以注册一个TransactionSynchronization,它允许您在调用时自动执行post-commit

TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization(){
           void afterCommit(){
                //do what you want to do after commit
           }
})

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

ehxuflar

ehxuflar2#

归功于Growerek的回答和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();
    }
}
iqjalb3h

iqjalb3h3#

自Spring 4.2以来,已经可以为post commit事件(或更一般的transaction synchronization events,例如transaction)定义侦听器。回滚)。这是基于Core Spring中的事件处理。使用这种方法测试代码更容易,因为您避免了对TransactionSynchronizationManager的直接依赖,而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
}

然后使用@TransactionalEventListener定义一个侦听器。默认情况下,这将在成功提交后执行,但可以使用phase参数进行更改:

// NewCustomerEventListener.java
@Component
public class NewCustomerEventListener {

    @TransactionalEventListener
    public void handleNewCustomerEvent(NewCustomerEvent newCustomerEvent) {
        // handle new customer event
    }
}

最后,您使用一个ApplicationEventPublisher来增强您的事务服务,一旦发送了所有事务语句,您就在该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));
    }

}

另请参阅:

0aydgbwb

0aydgbwb4#

在我的一个项目中,由于某些原因,我也不得不使用PlatformTransactionManager。所以我不得不使用org.springframework.transaction.support.TransactionTemplate
http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/transaction/support/TransactionTemplate.html
主要的好处是,如果你正确地实现了PlatformTransactionManager,你就不需要手动提交/回滚。至少TransactionTemplate的源代码可以帮助你,如果你需要更具体的东西。
使用它非常简单:
config.xml

<bean name="transactionTemplate"
            class="org.springframework.transaction.support.TransactionTemplate">
    <property name="transactionManager" ref="platformTransactionManager"/>
</bean>

MyServiceImpl.java

@Service
public class MyServiceImpl implements MyService {

    @Autowired
    private TransactionTemplate transactionTemplate;

    public Entity getSomethingWithTx(final long id) {

        return transactionTemplate.execute(new TransactionCallback&lt;Entity>() {
            @Override
            public Entity doInTransaction(TransactionStatus status) {
                //TODO implement
            }
        });
    }
}

相关问题