欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

drools中query的用法小结,

来源: javaer 分享于  点击 45315 次 点评:70

drools中query的用法小结,


目录
  • 一、背景
  • 二、需求
  • 三、前置需求
    • 1、query的语法结构
    • 2、java中如何获取query的结果
  • 四、实现
    • 1、无参数query的使用
      • 1、drl文件编写
      • 2、java文件编写
    • 2、有参数query的使用
      • 1、drl文件编写
      • 2、java文件编写
    • 3、java代码中openLiveQuery的使用
      • 1、drl文件编写
      • 2、java文件编写
      • 3、输出结果
    • 4、rule中使用query
    • 五、完整代码
      • 六、参考链接

        一、背景

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

        二、需求

        1、无参数query的使用
        2、有参数query的使用
        3、java代码中openLiveQuery的使用
        4、rule中使用query

        三、前置需求

        1、query的语法结构

        query queryName(参数列表)
        end

        注意事项:

        query的名字在同一个KIE base的所有包中必须要唯一,一般情况下我们全局唯一即可。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的使用的文章就介绍到这了,更多相关drools query使用内容请搜索3672js教程以前的文章或继续浏览下面的相关文章希望大家以后多多支持3672js教程!

        您可能感兴趣的文章:
        • SpringBoot整合Drools规则引擎动态生成业务规则的实现
        • SpringBoot整合Drools的实现步骤
        • SpringBoot2整合Drools规则引擎及案例详解
        • Drools Fusion(CEP)定义及使用方法讲解
        • Spring Boot+Drools规则引擎整合详解
        相关栏目:

        用户点评