关于insert和insertLogical在官网上的介绍,可以看如下链接
3.2. Inference and truth maintenance in the Drools engine
Drools引擎中的推理和真相维护
为了确保将相关数据应用于适当的规则,Drools引擎会根据现有知识进行推断,并根据推断出的信息执行操作。
例如,以下DRL规则确定了成年人的年龄要求,例如在公交车证政策中:
定义年龄要求的规则
rule "Infer Adult"
when
$p : Person(age >= 18)
then
insert(new IsAdult($p))
end
根据此规则,Drools引擎会推断一个人是成人还是儿童,并执行指定的操作(then的结果),每个18岁以上的人都会在工作存储器中插入一个IsAdult实例。 然后,可以在任何规则(例如以下规则段)中调用这种推断的年龄和公交车通行关系:
$p : Person()
IsAdult(person == $p)
在许多情况下,规则系统中的新数据是其他规则执行的结果,而这些新数据可能会影响其他规则的执行。
如果Drools引擎由于执行规则而断言数据,则在将推断的信息应用于其他规则时,Drools引擎将使用truth maintenance来证明断言的合理性并强制实施truthfulness。 truth maintenance还有助于发现矛盾并处理矛盾。 例如,如果执行了两个规则并导致矛盾的动作,则Drools引擎将根据先前计算得出的结论中的假设来选择动作。
Drools引擎使用陈述或逻辑插入来插入事实:
- Stated insertions: insert();使用该方法插入的Fact,该fact通常需要显示删除。该对象成为stated对象
- Logical insertions:inertLogical();进行逻辑插入后,如果插入fact的规则中的条件不再成立,则插入的fact将自动删除。当没有条件支持逻辑插入时,这些逻辑插入的fact将被删除。 Drools引擎认为逻辑上插入的fact是会被Drools引擎理解为justified对象。
我们看下官网给的例子(自己进行了一些调整)
package org.drools.examples.buspass.vo;
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Person person = (Person) o;
if (age != person.age) {
return false;
}
if (!name.equals(person.name)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + age;
return result;
}
}
package org.drools.examples.buspass.vo;
public class BusPass {
private Person person;
public BusPass(Person person) {
this.person = person;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
@Override
public String toString() {
return "AdultBusPass{" + "person=" + person + '}';
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
BusPass that = (BusPass) o;
if (!person.equals(that.person)) {
return false;
}
return true;
}
@Override
public int hashCode() {
return person.hashCode();
}
}
package org.drools.examples.buspass.vo;
public class AdultBusPass extends BusPass {
public AdultBusPass(Person person) {
super(person);
}
@Override
public String toString() {
return "AdultBusPass{" + "person=" + getPerson() + '}';
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
AdultBusPass that = (AdultBusPass) o;
if (!getPerson().equals(that.getPerson())) {
return false;
}
return true;
}
@Override
public int hashCode() {
return getPerson().hashCode();
}
}
package org.drools.examples.buspass.vo;
public class ChildBusPass extends BusPass {
public ChildBusPass(Person person) {
super(person);
}
@Override
public String toString() {
return "ChildBusPass{" + "person=" + getPerson() + '}';
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ChildBusPass that = (ChildBusPass) o;
if (!getPerson().equals(that.getPerson())) {
return false;
}
return true;
}
@Override
public int hashCode() {
return getPerson().hashCode();
}
}
package org.drools.examples.buspass.vo;
public class IsAdult {
private Person person;
public IsAdult(Person person) {
this.person = person;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
@Override
public String toString() {
return "IsAdult{" + "person=" + person + '}';
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
IsAdult isAdult = (IsAdult) o;
if (!person.equals(isAdult.person)) {
return false;
}
return true;
}
@Override
public int hashCode() {
return person.hashCode();
}
}
package org.drools.examples.buspass.vo;
public class IsChild {
private Person person;
public IsChild(Person person) {
this.person = person;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
@Override
public String toString() {
return "IsAdult{" + "person=" + person + '}';
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
IsChild isChild = (IsChild) o;
if (!person.equals(isChild.person)) {
return false;
}
return true;
}
@Override
public int hashCode() {
return person.hashCode();
}
}
BadExample(不是一个好例子)
public class BussPassBadExample {
public static void main(final String[] args) {
KieContainer kc = KieServices.Factory.get().getKieClasspathContainer();
KieSession ksession = kc.newKieSession("BussPassBadKS");
Person p = new Person("Yoda", 15);
/**
* 在使用具体的业务使用中,我们经常会通代码对Fact对象进行操作,<br/>
* Drools为我们提供了FactHandler来获取对象的句柄,通过此返回值可以对WorkingMemory中Fact对象进行操作。
*/
FactHandle fh = ksession.insert(p);
ksession.fireAllRules();
System.out.println("=================更新age=================");
p.setAge(16);
ksession.update(fh, p);
ksession.fireAllRules();
// Stateful rule session must always be disposed when finished
ksession.dispose();
}
}
drl文件
package org.drools.examples.buspass.bad;
import org.drools.examples.buspass.vo.Person;
import org.drools.examples.buspass.vo.ChildBusPass;
import org.drools.examples.buspass.vo.AdultBusPass;
rule IssueChildBusPass when
p : Person( age < 16 )
then
insert( new ChildBusPass( p ) );
end
rule IssueAdultBusPass when
p : Person( age >= 16 )
then
insert( new AdultBusPass( p ) );
end
rule ThereAreChildBusPass when
ChildBusPass()
then
System.out.println( "There are Child Bus Pass" );
end
rule ThereAreNoChildBusPass when
not ChildBusPass()
then
System.out.println( "There are no Child Bus Pass" );
end
rule ThereAreAdultBusPass when
AdultBusPass()
then
System.out.println( "There are Adult Bus Pass" );
end
rule ThereAreNoAdultBusPass when
not AdultBusPass()
then
System.out.println( "There are no Adult Bus Pass" );
end
执行结果
There are Child Bus Pass
There are no Adult Bus Pass
=================更新age=================
There are Adult Bus Pass
我们发现,该执行结果与预期的有些不一样,当age更新之后,已经不在是ChildBusPass了,但是规则文件中的 ThereAreNoChildBusPass 这条规则并没有执行。
goodExample(好的例子)
public class BussPassGoodExample {
public static void main(final String[] args) {
KieContainer kc = KieServices.Factory.get().getKieClasspathContainer();
KieSession ksession = kc.newKieSession("BussPassGoodKS");
Person p = new Person("Yoda", 15);
FactHandle fh = ksession.insert(p);
ksession.fireAllRules();
System.out.println("=================更新age=================");
p.setAge(16);
ksession.update(fh, p);
ksession.fireAllRules();
ksession.dispose(); // Stateful rule session must always be disposed when finished
}
}
drl文件
package org.drools.examples.buspass.good;
import org.drools.examples.buspass.vo.Person;
import org.drools.examples.buspass.vo.IsChild;
import org.drools.examples.buspass.vo.IsAdult;
import org.drools.examples.buspass.vo.ChildBusPass;
import org.drools.examples.buspass.vo.AdultBusPass;
rule IssueChildBusPass when
p : Person()
IsChild( person == p )
then
insertLogical( new ChildBusPass( p ) );
end
rule IssueAdultBusPass when
p : Person()
IsAdult( person == p )
then
insertLogical( new AdultBusPass( p ) );
end
rule ThereAreChildBusPass when
ChildBusPass()
then
System.out.println( "There are Child Bus Pass" );
end
rule ThereAreNoChildBusPass when
not ChildBusPass()
then
System.out.println( "There are no Child Bus Pass" );
end
rule ThereAreAdultBusPass when
AdultBusPass()
then
System.out.println( "There are Adult Bus Pass" );
end
rule ThereAreNoAdultBusPass when
not AdultBusPass()
then
System.out.println( "There are no Adult Bus Pass" );
end
rule ThereNoIsChild when
not IsChild()
then
System.out.println( "ThereNoIsChild" );
end
rule ThereNoIsAdult when
not IsAdult()
then
System.out.println( "ThereNoIsAdult" );
end
package org.drools.examples.buspass.good;
import org.drools.examples.buspass.vo.Person;
import org.drools.examples.buspass.vo.IsChild;
import org.drools.examples.buspass.vo.IsAdult;
rule IsChildPolicy when
p : Person( age < 16 )
then
insertLogical( new IsChild( p ) );
end
rule IsAdultPolicy when
p : Person( age >= 16 )
then
insertLogical( new IsAdult( p ) );
end
执行结果
There are Child Bus Pass
There are no Adult Bus Pass
ThereNoIsAdult
=================更新age=================
There are no Child Bus Pass
There are Adult Bus Pass
ThereNoIsChild
当Drools引擎在规则执行过程中逻辑插入Fact对象时,Drools引擎将通过执行规则来证明( justifies)对象的合理性。 对于每个逻辑插入,只能存在一个相等的对象(因此这里要覆盖equals()和hashCode()方法),并且随后的每个相等的逻辑插入都会增加该逻辑插入的justification计数器。 当规则的条件变为不真实时,将删除justification。 如果没有justification,逻辑对象将自动删除。
注意事项:对于逻辑删除,需要覆盖equals()和hashCode()方法
For logical insertions, your fact objects must override the equals
and hashCode
methods from the java.lang.Object
object according to the Java standard. Two objects are equal if their equals
methods return true
for each other and if their hashCode
methods return the same values. For more information, see the Java API documentation for your Java version.