调用insert()方法插入数据大家是都知道的,插入drools的数据对象会储存在 工作内存中,通常每次插入一个新的数据对象,drools引擎就会返回一个新的FactHandle对象实例,但是相同的数据对象仅会在工作内存中保留一个,当插入“相同”数据时,不会再插入新的实例,但会返回之前的FactHandle对象。
本文将分享drools7判断 数据对象之间相等的两种模式:identity 和 equality。两种模式下判断数据对象“相同”的策略完全不同。
通过设置系统参数 drools.equalityBehavior 的值可以改变drools计算运行时数据对象“相等”的模式。
identity :这种模式也是drools默认的。这种模式下,所有插入工作内存的运行时数据都保存在一个IdentityHashMap对象中,注意这个IdentityHashMap它是JDK自带的集合类,它判断两个元素相等跟hashcode和eaquls方法都没有关系,而是判断key值的地址值 即(k1 == k2)的方式(这里就不具体介绍这个知识点了,感兴趣的可以自行百度),所以它甚至可以允许两个hascode 和 equals 完全相同的两个对象同时插入工作内存。下面举个例子,感受一下它的特别:
entity:
public class Store {
private String id;
private String name;
//重写了 hashcode 方法 、equals方法、toString方法
@Override
public String toString() {
return "Store{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Store store = (Store) o;
return Objects.equals(id, store.id) &&
Objects.equals(name, store.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
// getter 和 setter ...
}
drl文件:
//这里不是java语法,这样写只是为了文章好看点
package rules;
import com.helloworld.entity.Store
rule "testStore"
when
$s:Store()
then
System.out.println($s.toString());
end
drools调用代码:
KieServices ks = KieServices.Factory.get();
//设置EqualityBehaviorOption 值为 IDENTITY,其实不设置的话,默认值也是IDENTITY
KieBaseConfiguration kbc = ks.newKieBaseConfiguration();
kbc.setOption(EqualityBehaviorOption.IDENTITY);
//创建kiebase
KieContainer kc = ks.getKieClasspathContainer();
KieBase kb = kc.newKieBase(kbc);
//创建两个hashcode 和 equals 都相同运行时数据,即,fact
Store s = new Store();
s.setId("1");
s.setName("用力的或者");
Store s1 = new Store();
s1.setId("1");
s1.setName("用力的或者");
//插入运行时数据
KieSession kieSession = kb.newKieSession();
FactHandle f = kieSession.insert(s);
FactHandle f1 = kieSession.insert(s1);
//判断两次插入返回的FactHandle 是否为同一个
System.out.println("f equals f1:"+ f.equals(f1));
//查看插入工作内存中数据个数
System.out.println("fact's count:"+kieSession.getFactCount());
//匹配规则
kieSession.fireAllRules();
kieSession.dispose();
Identity 模式下的运行结果:
f equals f1:false
fact's count:2
Store{id='1', name='用力的或者'}
Store{id='1', name='用力的或者'}
从结果看,两个Store实例都加入到了drools工作内存。
equality:这种模式下,使用hashcode方法和equals方法判断数据对象是否相同,这个比较容易理解,修改一下之前的示例:
实体类和drl文件与上例一致,drools调用代码需将 EqualityBehaviorOption 值设置为 EQUALITY
kbc.setOption(EqualityBehaviorOption.EQUALITY);
运行结果:
f equals f1:true
fact's count:1
Store{id='1', name='用力的或者'}
结果摆在这了,不用我说什么了吧。
也可以通过 kmodule.xml 设置 equalsBehavior 的值指定 equality模式,如下:
<kmodule>
<kbase name="kb" default="false" equalsBehavior="equality">
...
</kbase>
</kmodule>
最后,哪种模式更适合自己的业务,可以根据自己需求自行设置。文章写得比较简单,希望能对你有所帮助。