Grails에서 Domain 대상의 사무 제어 및 같은 대상의 중복 제출

3907 단어
이번 개발에서 발생한 두 가지 문제에 대해 주로 설명하고 두 가지 측면을 설명한다.
1. Grails Domain 트랜잭션 제어
2. 같은 프로세스에서 동일한 Domain 객체의 중복 제출
 
업무 설명
상품 정보를 대량으로 가져오려면 대량 가져오기 기록을 대량으로 가져와야 한다. 이 대량 데이터에 대한 통계를 실현해야 한다. 이는 모두 몇 개의 데이터를 가져오고 그 중에서 몇 개의 데이터를 성공했는지, 몇 개의 데이터를 실패했는지 포함한다.
1. 만약에 상품이 도입 요구(예를 들어 상품의 종류, 구역 등 판단)를 충족시키면 상품을 도입한다. 도입할 때 본 시스템의 데이터와 다른 업무 시스템의 데이터를 수정하고 두 업무 시스템의 데이터가 일치하도록 확보해야 한다(동시에 성공하거나 실패할 수 있다).다른 업무 시스템의 데이터 수정은 호출 인터페이스 방식을 통해 진행한다.
1.1 수정에 성공하고 성공으로 기록한다.
1.2 수정 실패, 실패로 기록한다.
>2. 만약에 상품이 도입 요구(예를 들어 상품의 종류, 구역 등 판단)를 만족시키지 못하면 상품을 도입하지 않고 실패로 기록한다.
기능 구현
가져올 파일을 업로드하고 업로드한 파일을 분석하며 관련 분석 데이터를list에 저장한 다음list를 순환합니다.다음은 위조 코드 설명입니다.
private Long saveList(List 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;
    }

이상 실현 코드
그러나 세 번째 인터페이스 이상을 호출할 때 스크롤이 필요할 때 다음과 같이 오류가 발생합니다.
Transaction rolled back because it has been marked as rollback-only
해결 방법:
방법
changeProduct
수정 후 다음을 수행합니다.
@Transactional(propagation = Propagation.REQUIRES_NEW)
private boolean changeProduct(String productId, BatchDomain batch){

}
수정 후 시스템은 원래 오류를 더 이상 포괄하지 않지만 다시 오류를 보고합니다.
a different object with the same identifier value was already associated with the session
해결 방법:
수정 방법
saveList(),
수정 방법은 다음과 같습니다.
private Long saveList(List 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
}
}
}

좋은 웹페이지 즐겨찾기