一、背景

我们知道在drools中是存在工作内存的,我们的Fact对象会加入到工作内存中,同时我们自己也可以在drl文件中使用insert/modify/update/delete等方法,修改工作内存中对象的,那么我们怎么查询修改之后的工作内存的值呢?而droolsquery可以帮助我们实现这个功能。

二、需求

1、无参数query的使用

2、有参数query的使用

3、java代码中openLiveQuery的使用

4、rule中使用query

三、前置需求

1、query的语法结构

query queryName(参数列表)

end

注意事项:

  1. query的名字在同一个KIE base的所有包中必须要唯一,一般情况下我们全局唯一即可。
  2. query没有whenthen的部分

2、java中如何获取query的结果

1、通过getQueryResults获取

QueryResults queryResults = kieSession.getQueryResults("query的名字",可选参数类表);

通过这种方式getQueryResults获取到的结果只会获取一次,如果工作内存中的数据发生了变化,则不会自动感知到。

2、通过openLiveQuery获取

kieSession.openLiveQuery("query的名字", new Object[]{可选参数}, new ViewChangedEventListener() {
@Override
public void rowInserted(Row row) {} @Override
public void rowDeleted(Row row) { } @Override
public void rowUpdated(Row row) {}
});

通过这种方式openLiveQuery是可以实时获取到结果的,当工作内存中的数据发生变化,这个地方是可以感知到的。

四、实现

此处只列出部分核心代码,一些无关的代码不列出。

1、无参数query的使用

1、drl文件编写

// 不带参数的查询
query "query01"
// 注意这个地方的 $p,java代码中需要用到
$p: Person(age < 18)
end

2、java文件编写

// 不带参数的query查询
QueryResults queryResults = kieSession.getQueryResults("query01");
queryResults.iterator().forEachRemaining(row -> {
// 那么这个地方的 $p 是怎么来的呢?其实是我们自己编写的drl query中写的
Person person = (Person) row.get("$p");
log.info("query01从工作内存中获取的query: {}", person);
});

2、有参数query的使用

1、drl文件编写

// 带参数的查询
query query02(Integer $age)
$p: Person(age < $age)
end

2、java文件编写

// 不带参数的query查询
// 带参数的query查询
queryResults = kieSession.getQueryResults("query02", 20);
queryResults.iterator().forEachRemaining(row -> {
Person person = (Person) row.get("$p");
log.info("query02从工作内存中获取的query: {}", person);
});

3、java代码中openLiveQuery的使用

1、drl文件编写

// 带参数的查询-查询工作内存Person对象的age的值小于外部传递进来的$age值
query query02(Integer $age)
$p: Person(age < $age)
end // 定义一个规则,当规则内存中的Person的age小于18时,直接年龄+1
rule "rule_test_live_query_in_java"
no-loop true
when
$p: Person($age:age < 18)
then
modify($p){
// 此处修改了工作内存中age对象的值
setAge($p.getAge() + 1)
}
System.out.println("更新来规则内存中Person["+$p.getName()+"]的age:["+$p.getAge()+"]值");
end

解释:

1、定义查询query02查询工作内存中的对象。

2、rule_test_live_query_in_java里面存在一个 modify($p) 这个操作会导致更新工作内存中对象的值。

3、no-loop true表达的是当前规则是否可以多次执行,就我们定义的这个规则,如果修改后的age<18那么可能还会导致规则的重新出发,加了no-loop true则只会触发一次。

2、java文件编写

public static void main(String[] args) {
KieServices kieServices = KieServices.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession("query-ksession");
kieSession.addEventListener(new DebugRuleRuntimeEventListener());
kieSession.addEventListener(new DebugAgendaEventListener());
kieSession.addEventListener(new DebugProcessEventListener()); // 实时查询
kieSession.openLiveQuery("query02", new Object[]{20}, new ViewChangedEventListener() {
@Override
public void rowInserted(Row row) {
Person person = (Person) row.get("$p");
log.info("实时查询-query02向工作内存中插入Person: {}", person);
} @Override
public void rowDeleted(Row row) {
Person person = (Person) row.get("$p");
log.info("实时查询-query02向工作内存中删除Person: {}", person);
} @Override
public void rowUpdated(Row row) {
Person person = (Person) row.get("$p");
log.info("实时查询-query02向工作内存中更新Person: {}", person);
}
}); Person person1 = new Person("张三", 16);
kieSession.insert(person1); kieSession.fireAllRules(); kieSession.dispose();
}

解释:

1、此处先使用了openLiveQuery查询。

2、让后向工作内存中insert(person1),并且触发了所有的规则fireAllRules

3、输出结果

10:08:54.415 [main] INFO com.huan.drools.querys.DroolsLiveQueryApplication - 实时查询-query02向工作内存中插入Person: Person(name=张三, age=16)
更新来规则内存中Person[张三]的age:[17]值
10:08:54.420 [main] INFO com.huan.drools.querys.DroolsLiveQueryApplication - 实时查询-query02向工作内存中更新Person: Person(name=张三, age=17)

可以看到,openLiveQuery实时查询到了工作内存中变更的对象。

4、rule中使用query

drl文件编写

// 定义一个查询,Person#name 需要以$prefix开头
query personNameStartsWith(String $prefix)
Person(name.startsWith($prefix))
end rule "rule_person_name_starts_with"
when
$p: Person($age:age < 18)
personNameStartsWith("张";) // 此处多个参数使用 , 分割,并且最后必须以 ; 结尾
then
System.out.println("在rule中使用query");
end

如果出现了如下异常Query's must use positional or bindings, not field constraints: "张" : [Rule name='rule_person_name_starts_with'],这个是因为我们在rule中调用query时,参数没有以;结尾。正确用法personNameStartsWith("张";)

?personNameStartsWith("张";) 和 personNameStartsWith("张";)是不一样的。The ? symbol means the query is pull only, once the results are returned you will not receive further results as the underlying data changes

五、完整代码

https://gitee.com/huan1993/spring-cloud-parent/tree/master/drools/drools-drl-query

六、参考链接

1、https://docs.drools.org/7.69.0.Final/drools-docs/html_single/index.html#drl-queries-con_drl-rules

drools中query的使用的更多相关文章

  1. (转载)MongoDB C#驱动中Query几个方法

    MongoDB C#驱动中Query几个方法 Query.All("name", "a", "b");//通过多个元素来匹配数组 Query ...

  2. 使用JPA中@Query 注解实现update 操作

    spring使用jpa进行update操作主要有两种方式: 1.调用保存实体的方法 1)保存一个实体:repository.save(T entity) 2)保存多个实体:repository.sav ...

  3. 【hql】spring data jpa中 @Query使用hql查询 问题

    spring data jpa中 @Query使用hql查询 问题 使用hql查询, 1.from后面跟的是实体类 不是数据表名 2.字段应该用实体类中的字段 而不是数据表中的属性 实体如下 hql使 ...

  4. drools中Fact的equality modes

    一.equality modes介绍 在drools中存在如下2种equality modes. 1.identity模式 identity:这是默认的情况.drools引擎使用IdentityHas ...

  5. drools中的条件 when

    目录 1.介绍 2.语法结构 3.模式例子 3.1 单个对象匹配 3.2 匹配任何对象 3.3 带条件匹配 3.3.1 注意事项 3.4 嵌套属性的匹配 3.4.1 访问单个嵌套属性 3.4.2 访问 ...

  6. drools中then部分的写法

    目录 1.背景 2.支持的方法 2.1 insert 插入对象到工作内存中 2.1.1 需求 2.1.2 drl文件编写 2.1.3 部分java代码编写 2.1.4 运行结果 2.1.5 结论 2. ...

  7. Elasticsearch DSL中Query与Filter的不同

    Elasticsearch支持很多查询方式,其中一种就是DSL,它是把请求写在JSON里面,然后进行相关的查询. 举个DSL例子 GET _search { "query": { ...

  8. MongoDB C#驱动中Query几个方法 (转)

    Query.All("name", "a", "b");//通过多个元素来匹配数组 Query.And(Query.EQ("nam ...

  9. hibernate中Query的list和iterator区别(续)

    打开cache后query的list和iterator方法区别 将query 的cache打开的话,缓存的是query本身,以hql 生成的 sql ,再加上参数,分页等信息做为key值,而不是que ...

随机推荐

  1. 学习zabbix(二)

    超大规模门户网站集群架构: 运维30%的时间都在监控,监控要多维度: 监控(单机监控(系统监控).网络监控.应用监控.分布式监控): 业务监控(业务指标-->流量分析-->舆论监控): 流 ...

  2. C语言break,return

    C语言break,continue,return的相似与区别 相同点: 都改变了程序的执行流程 区别是:break    用于循环和switch分支,跳出它所在分支或循环体到它所在的模块的      ...

  3. 顺利通过EMC实验(18)

  4. NE555脉冲模块电路

  5. ssm项目框架搭建(增删改查案例实现)——(SpringMVC+Spring+mybatis项目整合)

    Spring 常用注解 内容 一.基本概念 1. Spring 2. SpringMVC 3. MyBatis 二.开发环境搭建 1. 创建 maven 项目 2. SSM整合 2.1 项目结构图 2 ...

  6. 微信jssdk分享(附代码)

    老规矩---demo图: (注释:微信分享只支持右上角三个点触发) ======> 老规矩上菜: 1. 这边我封装了  share.js function allSharefun(param) ...

  7. 居中select中的option选项

    select经常有长短不一的选项:选择不同的选项居中不会生效: 使用text-align:center;text-align-last: center;  可以让所有选项都居中: 关于text-dec ...

  8. Ncrystal Skill设计

    在使用allegro时一般都会听说过skill,使用合适的Skill会使事情事半功倍.但是现阶段所能看到的个人白嫖的Skill都有一些通病.所以我才开发符合自己操作习惯的Skill. 当前我们所能找的 ...

  9. Python中用函数实现代码的复用

    # Python中用函数实现代码复用 """ def funcname(paras): statements return [expression] 关于函数定义说明如下 ...

  10. Typora教程

    写Mrakdown费事?Typora让你像写Word一样行云流水,所见即所得. ###简介 Typora是一款轻便简洁的Markdown编辑器,支持即时渲染技术,这也是与其他Markdown编辑器最显 ...