2015-11-24 26 views
0

我正通過for循環遍歷控制器中上傳的CSV文件。如果我的任何記錄包含錯誤,我需要能夠在GSP中顯示整個錯誤列表並且不保存任何記錄。如果沒有錯誤,則保存整批記錄。循環控制器中的Grails錯誤處理

我在grails中努力學習如何做到這一點。你是否迭代CSV文件兩次,第一次尋找錯誤,第二次處理數據庫提交?我是否創建錯誤列表並將其作爲flash.message發回?

我的代碼

def uploadFile() { 
    CsvToBean<EffortDetail> csvToBean = new CsvToBean<>(); 

    Map<String, String> columnMapping = new HashMap<String, String>(); 
    columnMapping.put("ExternalID", "alternateId"); 
    columnMapping.put("Full Name", "fullName"); 
    columnMapping.put("OrgKey", "orgkey"); 
    columnMapping.put("expenseDate", "expenseDate"); 
    columnMapping.put("projectHours", "projectHours"); 
    columnMapping.put("totalHours", "totalHours"); 

    HeaderColumnNameTranslateMappingStrategy<EffortDetail> strategy = new HeaderColumnNameTranslateMappingStrategy<EffortDetail>(); 
    strategy.setType(EffortDetail.class); 
    strategy.setColumnMapping(columnMapping); 

    MultipartFile file = request.getFile('file'); 

    if(file.empty) { 
     flash.message = "File cannot be empty" 
    } else { 
     List<EffortDetail> effortDetails = null; 
     CSVReader reader = new CSVReader(new InputStreamReader(file.getInputStream())); 
     effortDetails = csvToBean.parse(strategy, reader); 

     int count = 0; 

     //iterate for errors 
     for(EffortDetail effortDetail : effortDetails) { 
      println "loop 1 " + count++ 

      def recoveryDetailInstance = recoveryDetailService.populate(effortDetail) 
      // Test code to try and throw a list of flash messages 
      flash.message = count++; 
     } 

     count = 0; 

     //Iterate for commit 
     for(EffortDetail effortDetail : effortDetails) { 
      println "loop 2 " + count++ 

      def recoveryDetailInstance = recoveryDetailService.populate(effortDetail) 
      recoveryDetailInstance.save(flush:true,failOnError:true) 
     } 
    } 

    redirect (action:'upload') 
} 

.gsp

 <div class="col-md-12"> 
      <g:if test="${flash.message}"> 
       <div class="message" role="status"> 
        ${flash.message} 
       </div> 
      </g:if> 
      <g:eachError bean="${recoveryDetailInstance}"> 
       <li>${it}</li> 
      </g:eachError> 
      <g:uploadForm action="uploadFile"> 
       <span class="button"> <input type="file" name="file" /> <input 
        type="submit" class="upload" value="upload" /> 
       </span> 
      </g:uploadForm> 
     </div> 

回答

2

你需要考慮的事務。這裏是另一個Stackoverflow線程,我相信它正是你正在尋找的東西。

Grails - Saving multiple object, Rollback all object if one fails to save

的TLDR是從控制器移動您的處理邏輯到服務類方法。然後將你的循環合併成一個單獨的循環來完成驗證和域保存。如果有任何錯誤,則可以在調用回滾之後返回失敗域對象的列表。