我有以下情况:
我正在遍历Affiliate
实体,对于每个实体,我都需要在一个唯一的事务中保留和更新数据。因此,我有一个服务,该服务的方法带有以Spring @Transactional
注释为注释的方法(在该方法中创建和更新数据),但是我不知道如何查看该交易已被会员回滚?
我想知道对于特殊的Affiliate
事务已回滚并从我的服务中检索自定义错误代码。
这是我在使用Spring之前的服务:
public void savePostingPaymentDetails(List<Posting> postingsToUpdate, List<PaymentPostingDetail> detailsToInsert, Payment payment) {
logger.info("DB ACCESS : INSERT PAYMENT DETAILS & UPDATE POSTINGS");
long begin = System.nanoTime();
this.em.getTransaction().begin();
try {
// TEST
// 1 - Save Payments
this.em.persist(payment);
// 2 - Save Details
for (PaymentPostingDetail ppd : detailsToInsert) {
this.em.persist(ppd);
}
// 3 - Update Postings
for (Posting p : postingsToUpdate) {
if(p.getSignature() != null)
{
p.getSignature().setModification("withholding-tax.pay", new Date());
}
else
{
logger.error("The Posting with id = " + p.getIdentifier() + " has no PersistenceSignature ?!");
}
this.em.merge(p);
}
}
catch (Exception e)
{
logger.error("Unexpected error on saving/updating the DB.", e);
this.em.getTransaction().rollback();
logger.info("RollBack done.");
e.printStackTrace();
System.exit(JobStatus.ABNORMAL_END_OF_EXECUTION_ERROR.getCode());
}
this.em.getTransaction().commit();
logger.info("Details inserted & Postings updated.");
long end = System.nanoTime();
logger.info("Execution time = " + ((end-begin) / 1000000) + " milliseconds.");
logger.info("----------------------------------------------------------");
}
现在我有这个:
@Transactional
public void savePostingPaymentDetails(List<Posting> postings, List<PaymentPostingDetail> paymentDetails, Payment payment)
{
logger.info("DB ACCESS : INSERT PAYMENT DETAILS & UPDATE POSTINGS");
long begin = System.nanoTime();
this.paymentRepository.save(payment);
this.ppdRepository.save(paymentDetails);
for(Posting p : postings){
if(p.getSignature() != null)
{
p.getSignature().setModifiedAt(LocalDate.now());
p.getSignature().setModifiedBy(PayCopyrightWithholdingTaxProcess.SIGNATURE);
}
else{
p.setSignature(new PersistenceSignature(LocalDate.now(), PayCopyrightWithholdingTaxProcess.SIGNATURE));
}
this.postingRepository.save(p);
}
long end = System.nanoTime();
logger.info("Execution time = " + ((end-begin) / 1000000) + " milliseconds.");
logger.info("----------------------------------------------------------");
}
但是,如果事务已回滚,如何返回一个特殊的整数(而不是
System.exit()
)呢? 最佳答案
有一种叫做“用户管理的交易”(UMT)和“容器管理的交易”(CMT)的东西。
使用@Transactional
时,实际上是将事务管理委托给Spring容器(CMT),该容器负责例如为您打开和关闭事务。它
当像unchecked Exception
或NullPointerException
那样抛出RuntimeException
时,将自动回滚。对于检查
您必须指定应该在什么时候发生回滚的例外@Transactional(rollbackFor=myCheckedException.class)
。
您还可以侦听,观察TransactionalEventListener
的事务状态,并使用某些侦听代码来响应,例如here。但是您最终并没有管理事务,Spring正在为您做。发生某些特殊情况时,客户端代码无法对某些自定义代码做出反应,因为事务的管理委托给Spring。
因此,您必须依靠用户管理的事务,在其中打开事务,提交事务并在发生回滚的情况下做出反应。这正是UMT的目的:完全控制您的交易。
从您的旧代码中,您可能会得到类似:
public int savePostingPaymentDetails(List<Posting> postingsToUpdate, List<PaymentPostingDetail> detailsToInsert, Payment payment) {
int returnCode = 1 // 1 -> "success" , 0 -> "failure"
logger.info("DB ACCESS : INSERT PAYMENT DETAILS & UPDATE POSTINGS");
long begin = System.nanoTime();
long end = 0;
this.em.getTransaction().begin();
try {
// TEST
// 1 - Save Payments
this.em.persist(payment);
// 2 - Save Details
for (PaymentPostingDetail ppd : detailsToInsert) {
this.em.persist(ppd);
}
// 3 - Update Postings
for (Posting p : postingsToUpdate) {
if(p.getSignature() != null)
{
p.getSignature().setModification("withholding-tax.pay", new Date());
}
else
{
logger.error("The Posting with id = " + p.getIdentifier() + " has no PersistenceSignature ?!");
}
this.em.merge(p);
}
this.em.getTransaction().commit();
end = System.nanoTime();
}
catch (Exception e)
{
returnCode = 0;
logger.error("Unexpected error on saving/updating the DB.", e);
this.em.getTransaction().rollback();
logger.info("RollBack done.");
// e.printStackTrace();
System.exit(JobStatus.ABNORMAL_END_OF_EXECUTION_ERROR.getCode());
return returnCode;
}
//this.em.getTransaction().commit();
logger.info("Details inserted & Postings updated.");
//long end = System.nanoTime();
logger.info("Execution time = " + ((end-begin) / 1000000) + " milliseconds.");
logger.info("----------------------------------------------------------");
return returnCode = 1;
}
PS:顺便说一句,最佳实践是让您的提交失败时引发异常,而不是特殊代码。
您的新方法签名可能是:
public void savePostingPaymentDetails(List<Posting> postingsToUpdate, List<PaymentPostingDetail> detailsToInsert, Payment payment)
throws MyFailedDbOperationException, OtherException {
}
并在您的catch块上抛出异常
catch (Exception e)
{
logger.error("Unexpected error on saving/updating the DB.", e);
this.em.getTransaction().rollback();
logger.info("RollBack done.");
throw MyFailedDbOperationException("my db operation failed");
}
关于java - 如何知道回滚已执行? [@Transactional],我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49445666/