Spring transaction commit success event listener

Now that more and more microservices are done, the headache is getting more and more painful.

Cross-system transactions and cross-system paging are the most troublesome (in fact, headaches are useless and cannot be solved)

 

Now there is such a demand (in fact, the same demand has been seen a lot, and it has not been solved):

Insert records into the database and send the data to MQ for consumption by other systems.

After receiving the message, other systems will call the query interface to query for more information.

However, at this time, the transactions that may insert records have not yet been committed, so they cannot be queried at all.

 

The usual practice is to delay consumption (or delay sending):

For example, assuming that the transaction will be committed within a few minutes, then delay the query for 10 minutes.

Just inquire.

If the query fails, the transaction before the task is rolled back. .

 

In fact, if this scenario is in the spring environment, there are two solutions:

One is to use JMS, where spring provides transaction support.

But if you didn't use jms originally, this transformation will be heavier.

Another approach is event listening.

Let's talk about this method.

 

 Suppose the old-fashioned delayed send code is as follows:

    @Transactional(rollbackFor = Exception.class)
    public boolean insertSelectiveHeader(SupplierBillPO header) {
   ....
        int i = billPOMapper.insertSelective(header);
// Delay sending mq message
        service.delaySendMQ(header);
        return i > 0;
    }

 

 

After the transformation, we no longer use the service service that sends mq, but use

org.springframework.context.ApplicationEventPublisher;
    
    @Autowired
    private ApplicationEventPublisher publisher;

 Change the sending code to send the event:

    @Transactional(rollbackFor = Exception.class)
    public int insertSelectiveHeader(SupplierBillPO header) {
    ....
        int i = billPOMapper.insertSelective(header);
        publisher.publishEvent(header);
        return i;
    }

 The input parameter of publishEvent can be any custom object.

 

Then create a Bean class:

@Component
public class TransactionalMessageListener {
    
    @TransactionalEventListener(fallbackExecution = true)
    public void handleSupplierBillPush(SupplierBillPO data){
        service.sendImmediately(data);
    }
}

 This class must first be a bean, otherwise no one will listen to our events.

Then the method inside uses

import org.springframework.transaction.event.TransactionalEventListener;

 Annotate.

Methods do not have return values

The input parameters of the method are the same as the input parameters of the published event above.

In this way, spring will call this method after the transaction is successfully committed.

We can inject other services in it, such as sending MQ immediately (no delay now)

 

In fact, this annotation has other configurations, if you are interested, you can study it

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326189505&siteId=291194637