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(),修改后方法如下:
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 } } }
相关文章推荐
- Grails探索之访问存储过程及其事务控制
- oracle 中--怎么查看当前表空间在作什么操作?--查锁,死锁,当前执行时间长的Sql语句,没提交的事务,对象为哪些进程所用
- struts2 控制重复提交 Token
- SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因
- asp.net JS控制页面按钮在后台执行期间不重复提交
- NHibernate问题 flush-mode 一个事务中重复提交更新的SQL语句
- ActiveX数据对象之事务控制在VB和DELPHI中的应用
- 控制重复提交(表单spring,js等)
- SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因
- DATASNAP多表提交之事务控制之通用方法
- javascript控制页面表单重复提交
- grails去掉domain中关联对象的lazy策略
- Spring2.5MVC实现控制重复提交
- Spring控制多张数据表同时提交的事务操作
- 控制页面按钮在后台执行期间不重复提交的JS方法
- 在grails的服务中使用@Transactional来控制事务
- struts控制重复提交
- Grails 防止表单重复提交
- js控制再次点击按钮之间的间隔时间可防止重复提交
- js控制表单重复提交