如何在Spring Boot中部分回滚数据,错误将被持久化。

huangapple go评论126阅读模式
英文:

How to partially rollback data in spring boot, errors to be persited

问题

我在事务中有一系列表数据创建操作,使用springbootjavajpahibernate,序列如下所示。所使用的数据库是Oracle

  1. 下订单 - 插入到order_details_table表
  2. 处理付款 - 插入到payment_info表
  3. 错误消息(信息,警告,错误) - 插入到error_message表

如果在处理请求期间出现任何错误(信息,警告,错误),我会将错误消息插入到error_message表中。我的信息和警告消息会在没有错误发生时持久保存到error_message中。
但是,如果出现错误,我会从代码中抛出错误以回滚transaction,虽然它能够运行,但是我的error_message也会被回滚。

我想要回滚details_tablepayment_info,但不回滚error_message,我希望它们能够被持久化。

我如何实现相同的效果?

英文:

I have sequence of table data creation in transaction, using springboot, java, jpa and hibernate sequence shown below. Database used is Oracle

  1. Place order - insert into order details_table
  2. Process Payment - insert into payment_info table
  3. Error Message(info, warning, error) - insert into error_message table

I am inserting error messages in error_message table if any error occurs(info, warning, error).<br/>
My info and warning message get persisted into error_message if no error occurs during the processing of the request.
But if there is an error, I am throwing an error from code to rollback the transaction, its working but my error_message also get rollback.

I want to rollback details_table and payment_info but not the error_message, I want them to be persisted.

How I can achieve the same?

答案1

得分: 1

使用两个不同的事务。

默认的事务传播方式是REQUIRED,当在没有事务上下文的情况下调用带有@Transactional注解的方法时,将会启动一个新的事务,但如果已经存在事务,则会加入该事务,最终形成一个单一事务。如果发生回滚,所有操作将会回滚,因为它们属于同一个事务。

将事务传播方式更改为REQUIRES_NEW,以始终强制启动新事务(而不是加入已存在的事务)。这将允许您独立于付款信息提交错误消息事务。

@Transactional
public void placeOrder(Order oder) {
  // 处理订单
  
  paymentGateway.processPayment();

  // 保存订单 <- 这里的异常会回滚当前事务,但不会影响PaymentGateway中的事务,因为它是独立的
} 

// 在PaymentGateway中
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void processPayment() {
  // 处理付款
  // 插入错误消息
}

进一步阅读:了解PROPAGATION_REQUIRED。确保您还理解异常如何影响事务。

英文:

Use two different transactions.

The default transaction propagation is REQUIRED, when calling your @Transactional annotated method without a transactional context, a new transaction will be started but if there's already a transaction in place, the transaction will be joined, ending up with a single transaction. In case of rollback, all operations will be rollbacked as they belong to the same transaction.

Change the transaction propagation to REQUIRES_NEW in order to always force starting a new transaction (instead of joining it if there's one). This will allow you to commit the error messages transaction independently from the payment info.

@Transactional
public void placeOrder(Order oder) {
  // process order
  
  paymentGateway.processPayment();

  // save order &lt;- an exception here will rollback the current 
  // transaction but not the one in PaymentGateway which is independent
} 

// In PaymentGateway
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void processPayment() {
  // process payment
  // insert error messages
}

Further reading: Understanding PROPAGATION_REQUIRED. Make sure you also understand how exceptions affect transactions.

huangapple
  • 本文由 发表于 2020年10月9日 12:02:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/64273779.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定