1. Introduction to equality modes

In drools there are the following 2 equality modes.

1. Identity mode

identity : This is the default case. The drools engine uses IdentityHashMap to hold all Fact objects inserted into working memory. For each insertion of a new object, a new FactHandle object is returned. If the object is inserted repeatedly, the existing FactHandle object is returned.

Example:

 Person p1 = new Person("zhangsan", 20, "湖北罗田");
Person p2 = new Person("zhangsan", 20, "湖北黄冈罗田");

FactHandle factHandle1 = kieSession.insert(p1);
FactHandle factHandle2 = kieSession.insert(p2);
FactHandle factHandle3 = kieSession.insert(p2);

For the above example, factHandle1 != factHandle2 but factHandle2 == factHandle3 . That is, there will be two Person objects in the working memory.

2. Equality mode

equality : The drools engine uses HashMap to save all Fact objects inserted into working memory. In this mode, if a new object is inserted into drools, only if the object does not exist ( according to the object's hashcode and equals judgment ) will return a new FactHandle otherwise return the existing FactHandle .

Example:

 // 重写了Person对象的hashcode和equals方法
Person p1 = new Person("zhangsan", 20, "湖北罗田");
Person p2 = new Person("zhangsan", 20, "湖北黄冈罗田");

FactHandle factHandle1 = kieSession.insert(p1);
FactHandle factHandle2 = kieSession.insert(p2);
FactHandle factHandle3 = kieSession.insert(p2);

For the above example, factHandle1 == factHandle2 but factHandle2 == factHandle3 . That is, there will be one Person object in the working memory.

2. Demand

We have a Person object with the following 3 attributes name,age和address , which rewrites the hashcode and equals methods of the object's name和age .

  1. Insert objects into working memory multiple times and see what happens.
  2. Insert the same object to see if the obtained FactHandle object is the same.

3. How to set the equality behavior of the fact object

Here is a method to configure through kmodule.xml

 <kmodule xmlns="http://www.drools.org/xsd/kmodule">
    <kbase name="kbase-identity" packages="rules" default="false" equalsBehavior="identity">
        <ksession name="ksession-01" default="false" type="stateful"/>
    </kbase>
    <kbase name="kbase-equality" packages="rules" default="false" equalsBehavior="equality">
        <ksession name="ksession-02" default="false" type="stateful"/>
    </kbase>
</kmodule>

It can be seen from the above code that it is configured by configuring the kbase equalsBehavior attribute under ---357ee37fcb3148130a832b1c655f0c62---.

其余的配置方法,参考下图:
01-设置fact对象的equality行为

Fourth, the encoding implementation

1. Project structure diagram

02-项目结构图

2. Pour into the jar package

 <dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-bom</artifactId>
            <type>pom</type>
            <version>7.69.0.Final</version>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-compiler</artifactId>
    </dependency>
    <dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-mvel</artifactId>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.11</version>
    </dependency>
</dependencies>

3. Write the Person object

 public class Person {
    private String name;
    private Integer age;
    private String address;

    public Person(String name, Integer age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(name, person.name) && Objects.equals(age, person.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

Notice:
This object needs to override the hashcode and equals methods.

4. Write the kmodule.xml file

In this configuration file, kbase needs to be specified on equalsBehavior to determine the equality modes of the Fact object.

 <kmodule xmlns="http://www.drools.org/xsd/kmodule">
    <kbase name="kbase-identity" packages="rules" default="false" equalsBehavior="identity">
        <ksession name="ksession-01" default="false" type="stateful"/>
    </kbase>
    <kbase name="kbase-equality" packages="rules" default="false" equalsBehavior="equality">
        <ksession name="ksession-02" default="false" type="stateful"/>
    </kbase>
</kmodule>

Notice:
Need to see the value of 2 equalsBehavior

5. Write a rules file

 package rules

import com.huan.drools.Person

// 定义规则
rule "rule_01"
    when
        $p: Person()
    then
        System.out.println(Thread.currentThread().getName() + " name:"+$p.getName()+" age:"+$p.getAge());
end

The content in the rule file is very simple. As long as the Person object exists in the working memory, the values of name and age of this object are output.

6. Identity mode test

1. Write test code

 public class DroolsApplication {
    public static void main(String[] args) {
        equalsBehaviorIdentity();
    }

    private static void equalsBehaviorIdentity() {
        KieServices kieServices = KieServices.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        // 注意此处的 ksession-01
        KieSession kieSession = kieContainer.newKieSession("ksession-01");
        kieSession.addEventListener(new DebugRuleRuntimeEventListener());

        Person p1 = new Person("zhangsan", 20, "湖北罗田");
        Person p2 = new Person("zhangsan", 20, "湖北黄冈罗田");

        FactHandle factHandle1 = kieSession.insert(p1);
        FactHandle factHandle2 = kieSession.insert(p2);
        FactHandle factHandle3 = kieSession.insert(p2);
        kieSession.fireAllRules();

        kieSession.dispose();
    }   
}

2. Running results

identity
For a detailed explanation, see the description in the figure above.

7. Equality mode test

1. Write test code

 public class DroolsApplication {
    public static void main(String[] args) {
        equalsBehaviorEquality();
    }

    private static void equalsBehaviorEquality() {
        KieServices kieServices = KieServices.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession("ksession-02");
        kieSession.addEventListener(new DebugRuleRuntimeEventListener());

        Person p1 = new Person("zhangsan", 20, "湖北罗田");
        Person p2 = new Person("zhangsan", 20, "湖北黄冈罗田");

        FactHandle factHandle1 = kieSession.insert(p1);
        FactHandle factHandle2 = kieSession.insert(p2);
        FactHandle factHandle3 = kieSession.insert(p2);
        kieSession.fireAllRules();

        kieSession.dispose();
    }
}

2. Running results

equality

V. Conclusion

For the following code, look at the behavior under different equality modes

 Person p1 = new Person("zhangsan", 20, "湖北罗田");
 Person p2 = new Person("zhangsan", 20, "湖北黄冈罗田");

 FactHandle factHandle1 = kieSession.insert(p1);
 FactHandle factHandle2 = kieSession.insert(p2);
 FactHandle factHandle3 = kieSession.insert(p2);

Person The hashcode和equals method of the object has been rewritten, according to the first 2 parameters of the constructor.

1. In identity mode

factHandle1 != factHandle2 because p1 and p2 are 2 different objects.
factHandle2 == factHandle3 Because p2 is repeatedly added to the working memory, the working memory already exists at this time, so return the previously associated FactHandle

2. In equality mode

factHandle1 == factHandle2 == factHandle3 Because in this mode, it is necessary to compare the equals and hashcode objects according to the method of the object, and the Person object is rewritten 2 methods, so the return is the same.

6. Complete code

https://gitee.com/huan1993/spring-cloud-parent/tree/master/drools/drools-fact-equality-modes

7. Reference link

1. https://docs.drools.org/7.69.0.Final/drools-docs/html_single/index.html#fact-equality-modes-con_decision-engine


huan1993
218 声望34 粉丝

java工程师