spring-mvc - 使用 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);
}
}
}
解决方案
我通过在 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;
}
推荐阅读
- r - 使用频率表数据中的 ggplot 分组条形图
- python - 使用 Pandas 比较每 2 行并显示不同的
- amazon-web-services - 如何在 Windows Server 上的 Elastic Beanstalk 部署中正确使用 AWS Secrets Manager
- python - 如何找到两个不同维度图像python的RMSE?1920 x 1080 x 3 与 4361、7374、3
- php - Akeneo pim 5.0 安装数据库报错
- html - igu=1 参数的原始来源,用于在 iframe 中显示 google
- ios - ARKit + SceneKit:将重建场景用于物理?
- php - 如何使用 Laravel 外观
- php - Symfony @ParamConverter 仅适用于活动行
- python - 在 python 循环中测量矩阵距离