[英]Drools + Hibernate: Need to simulate Left Outer Join with OR condition in rule
使用下面的規則,我嘗試使用具有 OR 邏輯條件的規則匹配帳戶。 在這種情況下,我有一個賬戶表和一個這些賬戶的保險記錄表。 並非所有賬戶都有保險記錄。 Hibernate DAO 對象存在,並且存在從 Account 到 Insurance 的關聯。 我沒有觀察到這條規則的預期行為。 在這種情況下,我希望賬戶 1、2、3 和 4 匹配此規則,因為該規則應該匹配任何狀態為“非活動”的賬戶或任何 Insurance CURRENT_IND 值為“N”的賬戶。 但是,只有帳戶 2 和 4 與規則匹配。 僅當帳戶具有保險記錄時,它才會匹配規則。 我想要所有狀態 = 'Inactive' 的帳戶記錄,不管他們的保險記錄是否存在。
我目前正在使用 Drools 5.6.10.FINAL 和 Hibernate 3.6.0 對此進行測試。
是否可以使用帶有 Drools 的 Hibernate 創建這樣的規則? 是什么導致規則過濾保險記錄的存在?
package com.app.Testing
import com.app.abilities.RuleBuilder.EvalObject;
import com.app.dao.Insurance;
import com.app.dao.Account;
rule "Null Test"
when
$V1 : Account( )
$V2 : Insurance( ) from $V1.getInsurance()
$V3 : EvalObject(
$V2.getCurrentInd == "N" ||
$V1.getStatus == "Inactive"
)
then
reply.getReplyList().add("Null Test");
end
示例數據:
Account:
ACCT_ID STATUS
1 Inactive
2 Inactive
3 Inactive
4 Active
5 Active
Insurance:
ID CURRENT_IND
2 N
4 N
5 Y
使用“from”訪問某個事實的現成字段是完全沒有必要的——您可以通過綁定變量或getter訪問。 這就是導致問題的原因:無法將空值“從”轉換為模式,因此任何具有 insurance == null 的 Account 都會阻止進一步評估。
此外,我發現使用完全事實 (EvalObject) 來編寫相當巴洛克的布爾值。 一個簡單的 eval 應該很好,即使您必須使用非常糟糕的 Java 語法。
總之,以下規則會在您的所有四個帳戶上觸發:
rule "Better Test"
when
$V1: Account( $sta: status, $ins: insurance )
eval( $sta.equals( "Inactive" ) ||
$ins != null && $ins.getCurrentInd().equals( "N" ) )
then
System.out.println("Better Test " + $V1.getId() );
end
當然,邏輯是一件非常美妙的事情,如果應用得當,它會跟隨牽引繩的牽引力。 因此,您還可以使用一些規則:
rule "Third Test A"
when
$V1: Account( $sta: status == "Inactive" )
then
System.out.println("Third Test A " + $V1.getId() );
end
rule "Third Test B"
when
$V1: Account( $sta: status == "Active" )
Insurance( currentInd == "N" ) from $V1.getInsurance()
then
System.out.println("Third Test B " + $V1.getId() );
end
“啊”,我聽到你說,“他讓我使用兩個規則來處理一個可以做什么?復制 RHS 代碼?糟糕!”
不,不是我:這只是通往決賽的橋梁。 這個怎么樣:
rule "Fourth Test"
when
$V1: Account( $sta: status == "Inactive" )
or
($V1: Account( $sta: status == "Active" )
and
Insurance( currentInd == "N" ) from $V1.getInsurance()
)
then
System.out.println("Fourth Test " + $V1.getId() );
end
編輯如果一個帳戶可能與任意數量的 Insurance 事實相關聯(即 getInsurance 返回Collection<Insurance>
),則最后三個規則同樣有效。 但是,它們將針對currentInd == "N"
每個關聯保險觸發。 要將其減少為單個激活,請在保險模式前加上exists (或不為稍微不同的效果)。
考慮將依賴對象(保險)也作為事實輸入總是值得的。 此外,從孩子到父母(帳戶)的鏈接可能會改善問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.