1. Background

We know that in drools there is 工作内存 , our Fact object will be added to the working memory, and we can also be in drl --Use drl insert/modify/update/delete and other methods in the file to modify the objects in the working memory, so how do we query the value of the modified working memory? And drools of query can help us achieve this function.

2. Demand

1. Use of parameterless query
2. Use of parameter query
3. The use of openLiveQuery in java code
4. Use query in rule

3. Prerequisites

1. Grammatical structure of query

语法结构

 query queryName(参数列表)
    
end

Precautions:

  1. query的名字 In all packages of the same KIE base 必须要唯一 , in general, we can be globally unique.
  2. query No part of when and then

2. How to get the result of query in java

1. Obtained through getQueryResults

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

In this way getQueryResults the result obtained will only be obtained once, and if the data in the working memory has changed, it will not be automatically sensed.

2. Obtained through 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) {}
});

In this way openLiveQuery the result can be obtained in real time. When the data in the working memory changes, this place can be perceived.

4. Realization

Only some core codes are listed here, and some irrelevant codes are not listed.

1. Use of parameterless query

1. Writing drl files
 // 不带参数的查询
query "query01"
    // 注意这个地方的 $p,java代码中需要用到
    $p: Person(age < 18)
end
2. Writing java files
 // 不带参数的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. Use of parameter query

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

3. The use of openLiveQuery in java code

1. Writing drl files
 // 带参数的查询-查询工作内存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

explain:
1. Define the query query02 to query the objects in the working memory.
2. rule_test_live_query_in_java There is a modify($p) This operation will cause the value of the object in the working memory to be updated.
3. no-loop true expresses whether the current rule can be executed multiple times. As far as the rule we defined, if the revised age<18 may also cause the rule to start again, adding no-loop true will only trigger once.

2. Writing java files
 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();
}

explain:
1. Here we use the openLiveQuery query first.
2. Let backward working memory insert(person1) , and trigger all rules fireAllRules .

3. Output results
 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)

It can be seen that openLiveQuery queried the changed objects in the working memory in real time.

### 4. Use query in rule

drl File writing

 // 定义一个查询,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

If the following exception occurs `Query's must use positional or bindings, not field constraints:
"张" : [Rule name='rule_person_name_starts_with'] ,这个是因为我们在 rule 中调用 query 时,参数没有以 ; 结尾。正确用法 personNameStartsWith("张";) `

?personNameStartsWith("张";) 和 personNameStartsWith("张";) is different. The ? symbol means the query is pull only, once the results are returned you will not receive further results as the underlying data changes

5. Complete code

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

6. Reference link

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


huan1993
218 声望34 粉丝

java工程师