Drools7 插入数据对象的问题

          调用insert()方法插入数据大家是都知道的,插入drools的数据对象会储存在 工作内存中,通常每次插入一个新的数据对象,drools引擎就会返回一个新的FactHandle对象实例,但是相同的数据对象仅会在工作内存中保留一个,当插入“相同”数据时,不会再插入新的实例,但会返回之前的FactHandle对象。

        本文将分享drools7判断 数据对象之间相等的两种模式:identityequality。两种模式下判断数据对象“相同”的策略完全不同。

        通过设置系统参数 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>

最后,哪种模式更适合自己的业务,可以根据自己需求自行设置。文章写得比较简单,希望能对你有所帮助。

上一篇:==和equals()的区别?


下一篇:2021-09-15