[英]Hibernate one-to-many mapping - to fetch only one mapped record based on a criteria
[英]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.