您的位置:首页 > 大数据 > 人工智能

Grails中Domain对象的事务控制及同一对象的重复提交

2016-08-04 16:01 357 查看
主要对本次开发中遇到的两个问题进行说明,两个方面:

1、Grails Domain事务控制

2、在一个流程中同一个Domain对象的重复提交

 

业务描述

对商品信息进行批量导入,需对批量导入记录导入批次,实现对该批次数据中统计,包括:导入共多少条数据,其中成功了多少条,失败了多少条。

>1、如果商品满足导入要求(如商品种类,区域等判断),则对商品进行导入,导入时需对本系统中数据和另一个业务系统数据进行修改,并保证两个业务系统中数据是一致的(同时成功或者失败);对另一业务系统数据修改通过调用接口方式进行;

1.1、修改成功,记录为成功;

1.2、修改失败、记录为失败;

>2、如果商品不能满足导入要求(如商品种类,区域等判断),则对商品不进行导入,记录为失败;

功能实现

 上传需要导入的文件,对上传的文件进行解析,相关解析数据保存至list中,然后对list进行循环。以下为伪代码说明:

private Long saveList(List<String> list){
if(list.size()>0){
// 生成导入批次 ,设置该批次总数
BatchDomain batch = new BatchDomain();
batch.count = list.size();
batch.save(flush: true, failOnError: true);

//成功条数
int sucCount = 0;
//失败条数
int failCount = 0;
//对 list进行循环
for(String productId:list){
Boolean flag = changeProduct(productId, batch);
if(flag)
sucCount = sucCount + 1;
else
failCount = failCount + 1;
}
//修改导入批次的成功条数和失败条数
batch.sucCount = sucCount;
batch.failCount = failCount;
batch.save(flush: true, failOnError: true);
}
}

private boolean changeProduct(String productId, BatchDomain batch){
boolean flag = false;
//调用方法 checkProduct()判断是否满足导入要求,如果满足要求
if(checkProduct(productId)){
DetailDomainA.withTransaction { status ->
try{
//修改本系统数据
DetailDomainA detailA = new DetailDomainA();
detailA.productId = productId;
detailA.batch = batch;
detailA.save(flush: true, failOnError: true);
DetailDomainB detailB = new DetailDomainB ();
detailB.productId = productId;
detailB.batch = batch;
detailB.save(flush: true, failOnError: true);

//调用其他业务系统接口修改数据
boolean thirdFlag = ThirdServiceInterface.updateTT(productId);
if(thirdFlag){
flag = true;
}else{
status.setRollbackOnly();
}
}catch(Exception ex){
ex.printStackTrace();
status.setRollbackOnly();
}
}
}
return flag;
}
[align=justify]
[/align]
[align=justify]以上为实现代码[/align]
[align=justify]
[/align]
[align=justify]但是当调用第三个接口异常需要对回滚时,报错如下:[/align]
[align=justify]Transaction rolled back because it has been marked as rollback-only[/align]
[align=justify]解决方法:[/align]
对方法
changeProduct进行修改,修改后为:
[align=justify]@Transactional(propagation = Propagation.REQUIRES_NEW)[/align]
[align=justify]private boolean changeProduct(String productId, BatchDomain batch){[/align]
[align=justify]…[/align]
[align=justify]}[/align]
[align=justify]
[/align]
[align=justify]修改后,系统不再包原来错误,但又报一下错误:[/align]
[align=justify]a different object with the same identifier value was already associated with the session[/align]
[align=justify]解决方法:[/align]
修改方法
saveList(),修改后方法如下:
private Long saveList(List<String> list){
if(list.size()>0){
// 生成导入批次 ,设置该批次总数
BatchDomain batch = new BatchDomain();
batch.count = list.size();
batch.save(flush: true, failOnError: true);

//成功条数
int sucCount = 0;
//失败条数
int failCount = 0;
//对 list进行循环
for(String productId:list){
Boolean flag = changeProduct(productId, batch);
if(flag)
sucCount = sucCount + 1;
else
failCount = failCount + 1;
}
//修改导入批次的成功条数和失败条数
batch.sucCount = sucCount;
batch.failCount = failCount;
batch = batch.merge();
return batch.id
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息