java 如何在spring Boot 中实现方法内部发生异常时的事务回滚

uqdfh47h  于 2023-02-02  发布在  Java
关注(0)|答案(1)|浏览(169)

在spring Boot 中,如果在rest API方法中的任何地方发生异常,我会尝试回滚事务,但它只对特定的方法而不是所有的方法执行事务回滚,并且帮助我防止异常抛出后的响应。请忽略我的提问风格和格式。
下面是Rest API控制器类:

@RequestMapping(path = "/formDetails", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.POST)
    public ManadateFormResponse generateMandateForm(@RequestBody ManadateFormRequest manadateFormRequest,
            WebRequest request) throws Exception {
        
        ManadateFormResponse manadateFormResponse = new ManadateFormResponse();

        String errorStatus = environment.getRequiredProperty("rbi.status.error").trim();
        String adminZone = environment.getRequiredProperty("rbi.admin.zone").trim();
        String neft = environment.getRequiredProperty("payment.channel.type.neft").trim();
        String rtgs = environment.getRequiredProperty("payment.channel.type.rtgs").trim();
        String entityType = environment.getRequiredProperty("entity.type." + manadateFormRequest.getDutyType());

        try {
            
            Long[] l_tokens = nEFTRTGSService.validateChallans(manadateFormRequest.getSelectedChallans());

            final List<Long> tokens = Arrays.asList(l_tokens);
            List<EpaymentMainEntity> challans = nEFTRTGSService.loadChallans(Arrays.asList(l_tokens),
                    request.getLocale());

            List<Map<String, Object>> challanDetails = CommonFunctions.processMajorHeads(challans, adminZone);

            final Map<String, Object> basicData = CommonFunctions.getTotalDutyAndUserAndExpiryDate(challans);

            String referenceNumber = EpayRefID.generateReferenceNumber(entityType, manadateFormRequest.getDocType());
            if (referenceNumber.length() > 20) {
                throw new ReferenceNumberGenerationException(messages
                        .getMessage("message.exception.referenceNumberGenerationException", null, request.getLocale()));
            }

            nEFTRTGSService.initiatePayment(tokens, referenceNumber, challans, manadateFormRequest.getPaymentChannel(),
                    request.getLocale());

            
            new Thread(() -> {
                try {
                    
                    basicData.put("refernceNumber", referenceNumber);
                    basicData.put("challanDetails", challanDetails);
                    Map<String, Object> response = nEFTRTGSService.processNEFTRTGS(basicData);
                    String status_cd = ((String) response.get("Status_cd")).trim();
                    if (response == null || (status_cd).equals(errorStatus)) {
                        response = nEFTRTGSService.processNEFTRTGS(basicData);
                        
                        status_cd = ((String) response.get("Status_cd")).trim();
                        if (response == null || (status_cd).equals(errorStatus)) {
                            response = nEFTRTGSService.processNEFTRTGS(basicData);
                            
                        }
                    }
                    
                    List<EpaymentMainEntity> t_challans = nEFTRTGSService.loadChallans(Arrays.asList(l_tokens),
                            request.getLocale());

                    nEFTRTGSService.updateResponse(response, referenceNumber, t_challans);
                } catch (Exception e) {
                    throw new APIServiceException(e.getLocalizedMessage());

                }
            }).start();

            epay3Service.postPaymentDetails(new IGEpay3DTO(referenceNumber), request.getLocale());

            try {
                Object ExpDate = basicData.get("expiryDate");

                String strExpDate = String.valueOf(ExpDate);
                Date ExpDt = DateTimeUtility.parseJavaTimestamp(strExpDate);

                String dutyAmt = basicData.get("totalDuty").toString();
                BigDecimal totalDuty = new BigDecimal(dutyAmt);

                manadateFormResponse = nEFTRTGSService.generateMandateForm(referenceNumber, ExpDt, totalDuty,
                        request.getLocale());

            } catch (ManadateFormGenerationException exception) {
                throw exception;
            }
        } catch (Exception e) {
            throw new ManadateFormGenerationException(messages.getMessage("message.exception.manadateFormGenerationException", null, request.getLocale()));

        }

        return manadateFormResponse;

    }

实现中的所有方法在服务类中都有@Transactional,我尝试为REST API添加@Transactional,但仍然不起作用。考虑initiatePayment执行时没有任何异常,而processNEFTRTGS方法中发生了一些异常。它只回滚processNEFTRTGS方法,不回滚initiatePayment方法,并且它还提供响应返回manadateFormResponse。那么,如果在任何地方发生任何异常,我如何实现事务回滚,并且需要防止在发生任何异常时给出响应,例如initiatePayment、processNEFTRTGS、updateResponse执行无误,postPaymentDetails此时出现异常应回滚上述事务,且不应给予manadateFormResponse。

sqxo8psd

sqxo8psd1#

首先,如果您尚未配置事务管理器,则必须配置事务管理器:Transactions with Spring and JPA

@Configuration
@EnableTransactionManagement
public class PersistenceJPAConfig{

   @Bean
   public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
       //...
   }

   @Bean
   public PlatformTransactionManager transactionManager() {
      JpaTransactionManager transactionManager = new JpaTransactionManager();
      transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
      return transactionManager;
   }
}

然后将事务性注解放在目标方法的顶部:

@Transactional
public void saveTransaction(){
 saveSomethingIntoDb();
 throw new RuntimeException("Error");
}

现在事务管理器将回滚命令 saveSomethingIntoDb 中的数据库更改

相关问题