首页 > 解决方案 > 使用 Spting MVC 为列表中的每个项目打开新事务

问题描述

使用 Spring Boot 迭代列表时,我无法为每个项目打开新事务。我只想回滚失败的项目并继续列表中的其余项目。一个事务中有多个提交,如果任何失败都必须回滚。我的服务代码如下。

@Service("intentExportImportService")
public class IntentExportImportServiceImpl implements IntentExportImportService {
@Resource(name = "intentExportImportService")
private IntentExportImportService intentExportImportService;

 public  Map<String, Integer> importIntents(ExportImportData exportImportData,boolean overwrite) throws DataAccessLayerException {

    Map<String, Integer> statiscisMap= createOrUpdateIntent(exportImportData,overwrite);
    return statiscisMap;
}

private Map<String, Integer> createOrUpdateIntent(ExportImportData exportImportData,boolean overwrite)throws DataAccessLayerException {
    List<Intent> intentsList = exportImportData.getIntents();
    Map<String,Entity> entityMap = getEntityMap(exportImportData.getEntityList());
    Map<String,Api> apiMap = getApiMap(exportImportData.getApiList());
    Map<String,Integer> statisticsMap = new HashMap<>();
    Long domainId = ExcelUtil.getDomainId(exportImportData.getDomainName());
    for(Intent intent : intentsList) {
        Intent existingIntent =  intentExists(intent.getIntentNm());
       if(existingIntent != null){
           startUpdateIntent(intent,existingIntent,entityMap,apiMap,overwrite,statisticsMap,domainId);
       }else{
           startCreateIntent(intent,entityMap,apiMap,overwrite,statisticsMap,domainId);
       }
    }
    return statisticsMap;
}

@Transactional
public void startUpdateIntent(Intent intent, Intent existingIntent, Map<String, Entity> entityMap, Map<String, Api> apiMap, boolean overwrite, Map<String, Integer> statisticsMap, Long domainId) {

    try {
        intentExportImportService.updateIntent(intent, existingIntent, entityMap, apiMap, overwrite, statisticsMap,domainId);
    }catch (Exception e)
    {
        updateStatisticsMap(FAILED,statisticsMap);
        LOGGER.error("Error Importing Intents to update and hence rolling back intent: "+intent.getIntentNm());

    }
}

@Transactional(value = "dataTxManager", propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED, rollbackFor = {
    DuplicateException.class, DataAccessException.class,DataAccessLayerException.class, SQLTimeoutException.class, SQLException.class,Exception.class})
public void updateIntent(Intent intent, Intent existingIntent, Map<String, Entity> entityMap, Map<String, Api> apiMap, boolean overwrite, Map<String, Integer> statisticsMap,Long domainId) throws DataAccessLayerException {

    if(!overwrite){
        LOGGER.info("Not overwriting the Intent: "+intent.getIntentNm()+" as it already exist and overwrite is false");
        throw new DataAccessLayerException(CommonConstants.IMPORT_FAILURE_ERROR_CODE,"rolling back intent importing: "+intent.getIntentNm());
    }
    manageEntitiesAndApis(intent, entityMap, apiMap, overwrite,domainId);
    Long intentId = updateImportedIntent(intent,existingIntent);
    if(intentId != null) {
        updateStatisticsMap(UPDATED, statisticsMap);
    }
}

}

标签: spring-mvcspring-transactions

解决方案


我通过在 for 循环中添加 try catch 解决了这个问题,如下所示

 @Transactional
public Map<String, Integer> createOrUpdateIntent(ExportImportData exportImportData,boolean overwrite) {
    List<Intent> intentsList = exportImportData.getIntents();
    Map<String,Entity> entityMap = getEntityMap(exportImportData.getEntityList());
    Map<String,Api> apiMap = getApiMap(exportImportData.getApiList());
    Map<String,Integer> statisticsMap = new HashMap<>();
    Long domainId = ExcelUtil.getDomainId(exportImportData.getDomainName());
    for(Intent intent : intentsList) {
        try {
            Intent existingIntent = intentExists(intent.getIntentNm());
            if (existingIntent != null) {
                intentExportImportService.updateIntent(intent, existingIntent, entityMap, apiMap, overwrite, statisticsMap, domainId);
            } else {
                intentExportImportService.createIntent(intent, entityMap, apiMap, overwrite, statisticsMap, domainId);
            }
        } catch (DataAccessLayerException e) {
            updateStatisticsMap(FAILED,statisticsMap);
            LOGGER.error("Error Importing Intents to update and hence rolling back intent: "+intent.getIntentNm());
        }
    }
    return statisticsMap;
}

推荐阅读