2012-02-09 16 views
0

我需要一些hibernate/SQL幫助。我正在嘗試針對會計數據庫生成報告。佣金訂單可以有多個帳戶條目。Hibernate標準 - 基於一對多關係中的字段限制數據

 class CommissionOrderDAO { 
      int id 
      String purchaseOrder 
      double bookedAmount 
      Date customerInvoicedDate 
      String state 
      static hasMany = [accountEntries: AccountEntryDAO] 
      SortedSet accountEntries 

      static mapping = { 
       version false 
       cache usage: 'read-only' 
       table 'commission_order' 
       id column:'id', type:'integer' 
       purchaseOrder column: 'externalId' 
       bookedAmount column: 'bookedAmount' 
       customerInvoicedDate column: 'customerInvoicedDate' 
       state column : 'state' 
       accountEntries sort : 'id', order : 'desc' 
      } 
      ... 
     } 

     class AccountEntryDAO implements Comparable<AccountEntryDAO> { 
      int id 
      Date eventDate 
      CommissionOrderDAO commissionOrder 
      String entryType 
      String description 
      double remainingPotentialCommission 

      static belongsTo = [commissionOrder : CommissionOrderDAO] 

      static mapping = { 
       version false 
       cache usage: 'read-only' 
       table 'account_entry' 
       id column:'id', type:'integer' 
       eventDate column: 'eventDate' 
       commissionOrder column: 'commissionOrder' 
       entryType column: 'entryType' 
       description column: 'description' 
       remainingPotentialCommission formula : SQLFormulaUtils.AccountEntrySQL.REMAININGPOTENTIALCOMMISSION_FORMULA 
      } 

      .... 
     } 

報表的標準是commissionOrder.state ==開放和commissionOrder.customerInvoicedDate不爲空。而在報告中的會計分錄應起始日期和結束日期的之間以及與remainingPotentialCommission> 0

我期待顯示在CommissionOrder主要信息(並顯示的之間的佣金爲了的會計分錄日期),但是當我使用以下投影:

 def results = accountEntryCriteria.list { 
      projections { 
       like ("entryType", "comm%") 
       ge("eventDate", beginDate) 
       le("eventDate", endDate) 
       gt("remainingPotentialCommission", 0.0099d) 
       and { 
        commissionOrder { 
        eq("state", "open") 
        isNotNull("customerInvoicedDate") 
        } 
       } 
      } 
      order("id", "asc") 
     } 

我得到正確的commissionOrders正確accountEntries,但我倒退的:我有accountEntries的負載,可以參考同一commissionOrder。 Aut當我查看我檢索的commissionOrders時,每個人都擁有其所有帳戶條目,而不僅僅是日期之間的帳戶條目。

然後,我循環遍歷結果,從accountEntriesList中獲取commissionOrder,並在結束日期後刪除該commissionOrder上的accountEntries,以便及時獲取所需的「快照」。

def getCommissionOrderListByRemainingPotentialCommissionFromResults(results, endDate) { 
    log.debug("begin getCommissionOrderListByRemainingPotentialCommissionFromResults") 
    int count = 0; 
    List<CommissionOrderDAO> commissionOrderList = new ArrayList<CommissionOrderDAO>() 
    if (results) { 
     CommissionOrderDAO[] commissionOrderArray = new CommissionOrderDAO[results?.size()]; 
     Set<CommissionOrderDAO> coDuplicateCheck = new TreeSet<CommissionOrderDAO>() 
     for (ae in results) { 
      if (!coDuplicateCheck.contains(ae?.commissionOrder?.purchaseOrder) && ae?.remainingPotentialCommission > 0.0099d) { 
       CommissionOrderDAO co = ae?.commissionOrder 
       CommissionOrderDAO culledCO = removeAccountEntriesPastDate(co, endDate) 
       def lastAccountEntry = culledCO?.accountEntries?.last() 
       if (lastAccountEntry?.remainingPotentialCommission > 0.0099d) { 
        commissionOrderArray[count++] = culledCO 
       } 
       coDuplicateCheck.add(ae?.commissionOrder?.purchaseOrder) 
      } 
     } 
     log.debug("Count after clean is ${count}") 
     if (count > 0) { 
      commissionOrderList = Arrays.asList(ArrayUtils.subarray(commissionOrderArray, 0, count)) 
      log.debug("commissionOrderList size = ${commissionOrderList?.size()}") 
     } 

    } 
    log.debug("end getCommissionOrderListByRemainingPotentialCommissionFromResults") 
    return commissionOrderList 
} 

請不要以爲我的印象是這不是查理狐步。查詢本身不需要很長時間,但剔除過程需要35分鐘以上。現在,這是「可管理的」,因爲我只需要每月運行一次報告。我需要讓數據庫處理這個處理(我認爲),但我無法弄清楚如何操縱hibernate來獲得我想要的結果。我如何更改我的標準?

回答

0

試着縮小這個過程的瓶頸。如果你有很多數據,那麼這個檢查可能會花費很多時間。

coDuplicateCheck.contains(ae?.commissionOrder?.purchaseOrder) 
在設置

包含有O(n)的複雜性。您可以使用Map來存儲您要檢查的密鑰,然後搜索「ae?.commissionOrder?.purchaseOrder」作爲地圖中的關鍵字。

第二個想法是,也許當你獲得ae?.commissionOrder?.purchaseOrder時,它總是通過懶惰機制從db加載。嘗試打開查詢日誌記錄,並檢查您在此處理函數中沒有數十個查詢。

最後,我會建議縮小哪裏是最昂貴的部分和時間浪費。

This plugin也許有幫助。

+0

謝謝你,我會放棄! – Jaye 2012-02-11 18:17:40

+0

從Set 更改爲Map 並通過containsKey檢查purchaseOrder編號,將剔除過程從42分鐘加快到小於3.非常感謝您的建議! – Jaye 2012-02-14 14:58:47