繁体   English   中英

休眠条件-基于一对多关系中的字段限制数据

[英]Hibernate Criteria - Restricting Data Based on Field in One-to-Many Relationship

我需要一些休眠/ SQL帮助。 我正在尝试针对会计数据库生成报告。 佣金订单可以有多个针对其的帐户条目。

        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
            }

            ....
        }   

该报告的标准是:missionOrder.state == open,并且CommissionOrder.customerInvoicedDate不为null。 并且报表中的帐户条目应在startDate和endDate之间,且剩余的PotentialCommission> 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。 当我查看检索到的佣金订单时,每个订单都有其所有accountEntries,而不仅仅是两个日期之间的accountEntries。

然后,我遍历结果,从accountEntriesList中获取佣金订单,并在结束日期之后删除该佣金订单上的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
}

请不要以为我不是Charlie Foxtrot。 查询本身不会花费很长时间,但是剔除过程需要35分钟以上。 现在,它是“可管理的”,因为我每个月只需要运行一次报表。

我需要让数据库来处理此处理(我认为),但是我无法弄清楚如何操纵休眠来获取所需的结果。 如何更改我的标准?

尝试缩小该过程的瓶颈。 如果您有大量数据,那么此检查可能会很耗时。

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

Set中包含 O(n)复杂度。 您可以使用ie映射存储要检查的密钥,然后在映射中搜索“ ae?.commissionOrder?.purchaseOrder”作为密钥。

第二个想法是,也许当您获取ae?.commissionOrder?.purchaseOrder时,它总是通过惰性机制从db加载。 尝试打开查询日志记录,并检查此处理功能内部没有数十个查询。

最后我建议缩小最昂贵的零件和时间的浪费范围。

这个插件可能有帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM