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
.
- Insert objects into working memory multiple times and see what happens.
- 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---.
其余的配置方法,参考下图:
Fourth, the encoding implementation
1. Project structure diagram
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
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
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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。