我有简单的JAVA bean,有两个int字段:'a'和'b' .
我有两个规则:
rule "First rule"
salience 10
when
$bean : Bean ( a == 1)
then
$bean.setB(10);
end
rule "Second rule"
salience 20
when
$bean : Bean ( a == 1)
then
$bean.setB(20);
end
实际结果:“第二条规则”首先被解雇(更高的显着性),“第一条规则”被解雇第二条 .
预期结果:只触发一条规则(具有最高显着性) . 其他规则被忽略 . 这该怎么做? Drools有可能吗?我正在使用Drools 6.0.0 Final .
要求:1 . 我不能使用'activation-group' . 我不想在每个 beans 子上使用'收回' .
UPDATE
非常感谢你的回答 .
可能我应该详细描述我的问题 . 我有一套1500条规则 . 每条规则:
-
与同一个bean一起工作 - 这个bean有很多字段(属性),
-
有突出性,
-
有很多条件,
-
只有一个动作 - 在我的bean中设置一个(总是相同的)布尔标志 .
What I want to get? 当我遇到冲突时(输入事实由两个或更多规则匹配)我想只触发一个具有最高显着性的规则 . 应忽略针对这一事实的其他匹配规则 . 最重要的是性能 - 这应该尽可能快地工作 .
What I do? 目前我有两个解决方案,但我不知道哪个更好,或者我应该以不同的方式解决这个问题 .
解决方案1 - Statefull会话
Java代码:
for (Object fact : facts) {
FactHandle fh = session.insert(fact);
session.fireAllRules(1);
session.delete(fh);
}
解决方案2 - 无状态会话
Java代码:
for (Object fact : facts) {
session.execute(fact);
}
解决方案2的DRL文件:我在每个规则中添加了相同的激活组:
rule "Rule"
activation-group "group"
salience X
when
...
then
...
5 回答
您可以尝试的一种解决方案是“锁定活动”属性,以避免涉及一个或多个规则的无限执行循环 .
锁定活动由规则组限定,并且只要该组被聚焦,就会阻止规则重新启动 . 它不依赖于新事实或现有事实的更新,而只取决于议程重点 . 如果您不操纵组,这可能是一个选项 .
我将使用
activation-group
与salience
解决此问题,如解决方案2中所述根据你的问题,我担心你可能会误解突显点 . 显着性是优先级值 . Drools使用它来排除在满足多个规则的约束的情况下首先开始流口水 .
[在某些情况下解雇规则P并且在规则P被解雇时不规则Q]的问题是常见问题 . 您的对象模型应该设置为这是推理概念空间的自然结果 . 对于您列出的字面情况,您可以尝试将新事实插入工作内存(“RuleFiredFact”,其值为“2nd”或其他) . 然后,您将在第一个规则约束中检查此事实 . 如果是,则第一条规则不会触发 .
UPDATE: 为了清楚起见,"RuleFiredFact"是一个抽象占位符,用于表示事实模型中的某些具体事实 . 流口水的一部分不是在drools DSL中使用抽象的东西 .
UPDATE:
有状态与无状态会话是否合适将取决于您可用的计算机资源,对象模型,团队,列表还在继续 . 如果您不知道使用哪个,则应参考有关该主题的讨论 . 你可以试试这个旧的邮件列表http://drools.46999.n3.nabble.com/Advice-sought-on-choosing-Stateful-or-Stateless-sessions-td57069.html
无论你使用哪种方式,我都强烈怀疑你的物体模型太浅了 . 创建一个包含一个事实的drools系统是非常罕见的,然后再也不会创建 . 流口水的目的是推理一些事实 . 解决这个问题的方法可能就像移动你的对象并将其中的信息作为事实插入到drools工作内存中 . 然后,您将编写仅在您想要的约束下触发的规则 .
在我所描述的情况下,有很多方法可以确保只有一个规则触发 . 您的规则可能都在寻找“factWasAlreadyReasonedOverFact”,并引用了触发执行的事实 . 这是一个非常粗略的例子 . 希望它能给你一个想法 .
首先让我告诉你,你有一些奇怪的场景在这里:)
这个问题有多种解决方案:
使用Bean类的另一个属性来标记'processed'事实 .
使用自定义AgendaFilter
使用ksession.fireAllRules(1);
希望能帮助到你,
你可以使用drools.halt();在你最高的显着规则 .
这样做是为了终止流程并从规则执行中出来(正是你需要的) .