使用以下规则,我尝试使用具有OR逻辑条件的规则匹配帐户。在这种情况下,我有一个帐户表和这些帐户的保险记录表。并非所有帐户都有保险记录。存在Hibernate DAO对象,并且存在从Account到Insurance的关联。我没有观察到这条规则的预期行为。在这种情况下,我希望帐户1,2,3和4符合此规则,因为规则应匹配任何状态为"非活动"或任何保险CURRENT_IND值为' N'的帐户。但是,只有帐户2和4符合规则。只有具有保险记录的帐户才会匹配该规则。我希望所有帐户记录的状态='无效',无论其保险记录是否存在。
我目前正在使用Drools 5.6.10.FINAL和Hibernate 3.6.0进行测试。
是否可以使用Hibernate和Drools创建这样的规则?是什么导致规则过滤保险记录'存在?
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
答案 0 :(得分:2)
使用“from”访问某个事实的现成字段是完全没必要的 - 您可以通过绑定变量或getter访问。这就是导致问题的原因:无法将“null”值“转换”为模式,因此任何具有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代码?Phooey!”
不,不是我:这只是决赛的桥梁。怎么样:
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
修改如果某个帐户可能与任意数量的保险事实相关联(即getInsurance返回Collection<Insurance>
),则最后三个规则的工作状况一样好。但是,他们将为currentInd == "N"
的每个相关保险开火。要将此减少为单次激活,请使用存在(或不)为保险模式添加前缀,以获得稍微不同的效果。
总是值得考虑输入依赖对象(保险)作为事实。此外,从孩子到父母(帐户)的链接可以改善问题。