由于某些原因,我已经手动执行了事务提交并使用Spring PlatformTransactionManager回滚,我需要做的是设置一个钩子,以便在提交事务后进行事后提交操作。
看看:
void commit(TransactionStatus status) throws TransactionException;
我无法确定如何判断交易是否成功,而不是假设交易成功,如果没有引发任何指示。
我可以使用AOP作为一个选项,但是可以使用回调方法进行程序化操作呢?
答案 0 :(得分:43)
使用TransactionSynchronizationManager
和TransactionSynchronization
使用TransactionSynchronizationManager
,您可以使用静态方法获取有关当前事务的信息,并且可以注册TransactionSynchronization
,这样您就可以在调用时自动执行提交
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization(){
void afterCommit(){
//do what you want to do after commit
}
})
请注意,TransactionSynchronization是基于每个线程的(对于基本Web请求而言,这通常不是问题)。
答案 1 :(得分:12)
相信Grooveek的回答和Alex的评论 - 我把它放在这里,因为这些组合的建议提供了一个在网络上很难找到的可靠而简洁的解决方案。
使用Spring 4+。如果在成功提交后需要在@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();
}
}
方法上进行回调,只需在方法的开头添加:
set HTTP_PROXY="http://127.0.0.1:8888"
set HTTPS_PROXY="http://127.0.0.1:8888"
set NODE_TLS_REJECT_UNAUTHORIZED=0
答案 2 :(得分:5)
从Spring 4.2开始,就可以使用基于注释的配置为提交后事件(或更普遍的是事务同步事件,例如回滚)定义侦听器。这基于core 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
}
然后,您使用@TransactionalEventListener
定义一个侦听器。默认情况下,此操作将在成功提交后执行,但是可以使用phase
参数进行更改:
// NewCustomerEventListener.java
@Component
public class NewCustomerEventListener {
@TransactionalEventListener
public void handleNewCustomerEvent(NewCustomerEvent newCustomerEvent) {
// handle new customer event
}
}
最后,在发送所有交易对帐单后,您会用ApplicationEventPublisher
来增强您的交易服务。
// 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));
}
}
另请参阅:
答案 3 :(得分:1)
在我的一个项目中,由于某些原因,我还必须使用PlatformTransactionManager
。所以我被迫使用org.springframework.transaction.support.TransactionTemplate
。
主要的好处是,如果您已正确实施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<Entity>() { @Override public Entity doInTransaction(TransactionStatus status) { //TODO implement } }); }