簡體   English   中英

Drools + Hibernate:需要在規則中使用 OR 條件模擬 Left Outer Join

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM