Критерии гибернации - ограничение данных на основе поля в отношениях один-ко-многим - PullRequest
0 голосов
/ 09 февраля 2012

Мне нужна помощь в спящем режиме / 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
            }

            ....
        }   

Критерием для отчета является то, что CommissionOrder.state == open, а значение CommissionOrder.customerInvoicedDate не равно нулю. И записи учетной записи в отчете должны быть между startDate и endDate и с оставшимся ПотенциалCommission> 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")
        }   

Я получаю правильные AccountEntries с правильными комиссионными, но я возвращаюсь назад: у меня есть множество accountEntries, которые могут ссылаться на один и тот же CommissionOrder. Когда я смотрю на заказы на заказ, у каждого из них есть ВСЕ свои учетные записи, а не только учетные записи между датами.

Затем я зацикливаюсь на результатах, получаю CommissionOrder из accountEntriesList и удаляю accountEntries для данного CommissionOrder после даты окончания, чтобы получить «моментальный снимок» в нужное время.

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 минут. Прямо сейчас, это "управляемо", потому что я должен запускать отчет только один раз в месяц.

Мне нужно разрешить базе данных обрабатывать эту обработку (я думаю), но я не мог понять, как манипулировать спящим режимом для получения желаемых результатов. Как я могу изменить свои критерии?

1 Ответ

0 голосов
/ 11 февраля 2012

Попробуйте сузить горлышко бутылки этого процесса.Если у вас много данных, то, возможно, эта проверка может быть дорогостоящей.

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

в наборе содержит со сложностью O (n).Вы можете использовать т. Е. Карту для хранения ключей, которые вы бы проверили, а затем выполнить поиск "ae? .CommissionOrder? .PurchaseOrder" в качестве ключа на карте.

Вторая мысль: возможно, когдаВы получаете a.? commmissionOrder? .purchaseOrder это всегда загружается из БД ленивым механизмом.Попробуйте включить ведение журнала запросов и убедитесь, что у вас нет десятков запросов внутри этой функции обработки.

В заключение, снова и снова, я бы хотел сузить круг наиболее дорогих деталей и затрат времени.

Этот плагин может быть полезным.

...