我需要一些hibernate / 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不为null。并且报告中的帐户条目应该在startDate和endDate之间,并且在remainingPotentialCommission&gt;之间。 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。
然后我遍历结果,从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 :(得分:0)
尝试缩小该过程的瓶颈。如果您有大量数据,那么这项检查可能需要花费大量时间。
coDuplicateCheck.contains(ae?.commissionOrder?.purchaseOrder)
Set contains 中的具有O(n)复杂度。您可以使用例如Map来存储您要检查的密钥,然后在地图中搜索“ae?.commissionOrder?.purchaseOrder”作为密钥。
第二个想法是,当你得到ae?.commissionOrder?.purchaseOrder时,它总是通过懒惰机制从db加载。尝试打开查询日志记录并检查您在此处理函数中没有数十个查询。
我会建议缩小哪里是最昂贵的部分和时间浪费。
This plugin可能会有所帮助。