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:
-
query的名字
In all packages of the same KIE base必须要唯一
, in general, we can be globally unique. -
query
No part ofwhen
andthen
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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。