一、背景

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

二、需求

1、无参数query的使用

2、有参数query的使用

3、java代码中openLiveQuery的使用

4、rule中使用query

三、前置需求

1、query的语法结构

  1. query queryName(参数列表)
  2. end

注意事项:

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

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

1、通过getQueryResults获取

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

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

2、通过openLiveQuery获取

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

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

四、实现

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

1、无参数query的使用

1、drl文件编写

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

2、java文件编写

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

2、有参数query的使用

1、drl文件编写

  1. // 带参数的查询
  2. query query02(Integer $age)
  3. $p: Person(age < $age)
  4. end

2、java文件编写

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

3、java代码中openLiveQuery的使用

1、drl文件编写

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

解释:

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

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

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

2、java文件编写

  1. public static void main(String[] args) {
  2. KieServices kieServices = KieServices.get();
  3. KieContainer kieContainer = kieServices.getKieClasspathContainer();
  4. KieSession kieSession = kieContainer.newKieSession("query-ksession");
  5. kieSession.addEventListener(new DebugRuleRuntimeEventListener());
  6. kieSession.addEventListener(new DebugAgendaEventListener());
  7. kieSession.addEventListener(new DebugProcessEventListener());
  8. // 实时查询
  9. kieSession.openLiveQuery("query02", new Object[]{20}, new ViewChangedEventListener() {
  10. @Override
  11. public void rowInserted(Row row) {
  12. Person person = (Person) row.get("$p");
  13. log.info("实时查询-query02向工作内存中插入Person: {}", person);
  14. }
  15. @Override
  16. public void rowDeleted(Row row) {
  17. Person person = (Person) row.get("$p");
  18. log.info("实时查询-query02向工作内存中删除Person: {}", person);
  19. }
  20. @Override
  21. public void rowUpdated(Row row) {
  22. Person person = (Person) row.get("$p");
  23. log.info("实时查询-query02向工作内存中更新Person: {}", person);
  24. }
  25. });
  26. Person person1 = new Person("张三", 16);
  27. kieSession.insert(person1);
  28. kieSession.fireAllRules();
  29. kieSession.dispose();
  30. }

解释:

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

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

3、输出结果

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

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

4、rule中使用query

drl文件编写

  1. // 定义一个查询,Person#name 需要以$prefix开头
  2. query personNameStartsWith(String $prefix)
  3. Person(name.startsWith($prefix))
  4. end
  5. rule "rule_person_name_starts_with"
  6. when
  7. $p: Person($age:age < 18)
  8. personNameStartsWith("张";) // 此处多个参数使用 , 分割,并且最后必须以 ; 结尾
  9. then
  10. System.out.println("在rule中使用query");
  11. 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. HTML5打造原生应用——Ionic框架简介与Ionic Hello World

    试了试用Ionic框架打造了两个应用,然后在Google Play上架了. 程序语言答人 教你设计物联网 更有意思的是这是在一周的业余时间内完成的三个应用中的两个,接着让我们看看这个框架如何实现高效地 ...

  2. 解决 css 浮动后 父元素高度失效问题

    应用场景 子元素标签使用 浮动后,会出现浮在父元素上层,脱离了.导致父元素没办法根据子元素的高度而变化,提供以下解决方案. 解决代码 把 '.clearfix ' Class 样式添加到 父元素即可. ...

  3. background-clip 和 background-origin

    下面都是我自己的理解, 如果有不对的地方, 还请大家帮忙指出.下面是在 chrome 浏览器上测试的 background-clip 和 background-origin 先说说background ...

  4. JS 中的日期时间操作计算实例

    实例 一:已知日期格式为 "YYYY/MM/DD",计算相对于今天的天数差. function fromNow(date){ var mTimes = new Date(date) ...

  5. 使用 jfinal + beetl + bootstrap 实现商城展示及管理系统

    使用 jfinal+beetl 在线商品展示系统 使用 git clone https://github.com/zhouchong741/jfinal-demo.git 使用 IntelliJ ID ...

  6. PAT B1056组合数的和

    给定 N 个非 0 的个位数字,用其中任意 2 个数字都可以组合成 1 个 2 位的数字.要求所有可能组合出来的 2 位数字的和.例如给定 2.5.8,则可以组合出:25.28.52.58.82.85 ...

  7. 大数据学习之路又之从csv文件到sql文件的操作过程

    根据前几天的测试,简单的做个总结 csv文件的字段说明: 1.将csv文件上传到虚拟机中 在SecureCRT中点击,创建目录,直接把文件从本地拖拽进去 我放在了/linmob/data的路径下,所以 ...

  8. Vulnhub 之 Earth

    靶机地址:https://www.vulnhub.com/entry/the-planets-earth,755/ Kali IP:192.168.56.104 下载OVA文件后,直接通过Virtua ...

  9. VUE3 之 使用 Mixin 实现代码的复用 - 这个系列的教程通俗易懂,适合新手

    1. 概述 老话说的好:舍得舍得,先舍才能后得. 言归正传,今天我们来聊聊 VUE 中使用 Mixin 实现代码的复用. 2. Mixin 的使用 2.1 不使用 Mixin 的写法 <body ...

  10. phpshe xml注入

    *php商城系统 xml注入* **页面样式* *Xml原理参考:* https://www.cnblogs.com/20175211lyz/p/11413335.html *漏洞函数simplexm ...