2012-02-09 4 views
0

私はいくつかのhibernate/SQLのヘルプが必要です。会計データベースに対してレポートを生成しようとしています。手数料の注文に複数の勘定科目を登録することができます。Hibernate Criteria - 1対多の関係でフィールドに基づいてデータを制限する

 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がnullではないということです。そして、レポート内のアカウントのエントリは、私が主にCommissionOrderに関する情報を表示する(と間の手数料順のアカウントエントリを表示するために探していたstartDateとendDateに間と> 0

remainingPotentialCommissionにする必要があります日付)が、私は、次の投影を使用する場合:

 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を得るが、私は逆方向で行くよ:私は同じcommissionOrderを参照することができaccountEntriesの負荷を持っています。私が取り出したcommissionOrdersを見ると、それぞれのaccountEntriesには日付間のaccountEntriesだけでなく、すべてのaccountEntryがあります。

その後、結果をループして、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分以上かかります。今は、月に一度だけレポートを実行する必要があるため、管理が容易です。

データベースでこの処理を処理させる必要がありますが、私が望む結果を得るために休止状態を操作する方法を理解できませんでした。どのように基準を変更できますか?

答えて

0

このプロセスのボトルネックを絞り込んでください。大量のデータがある場合は、おそらくこのチェックに時間がかかる可能性があります。セット

coDuplicateCheck.contains(ae?.commissionOrder?.purchaseOrder) 

はO(n)の複雑さを持っている含ま。マップを使用すると、確認するキーを保存し、"ae?.commissionOrder?.purchaseOrder"をキーとしてキーで検索できます。

2つ目は、.commissionOrder?.purchaseOrderという名前のつもりで、dbから遅延ロードされることがあります。照会ロギングをオンにして、この処理機能内に数十の照会がないことを確認してください。

最後に、私は、最も高価な部分と時間の無駄がどこにあるかを絞り込むことを提案します。

This plugin多分役に立ちます。

+0

ありがとう、私はそれを行く! – Jaye

+0

Set からMap に変更し、containsKeyを使用してpurchaseOrder番号を確認すると、カルスプロセスが42分から3に短縮されました。アドバイスをいただきありがとうございます! – Jaye

関連する問題