drools中query的使用
一、背景
我们知道在drools
中是存在工作内存
的,我们的Fact
对象会加入到工作内存中,同时我们自己也可以在drl
文件中使用insert/modify/update/delete
等方法,修改工作内存中对象的,那么我们怎么查询修改之后的工作内存的值呢?而drools
的query
可以帮助我们实现这个功能。
二、需求
1、无参数query的使用
2、有参数query的使用
3、java代码中openLiveQuery
的使用
4、rule中使用query
三、前置需求
1、query的语法结构
文章图片
query queryName(参数列表)end
注意事项:
query的名字
在同一个KIE base的所有包中必须要唯一
,一般情况下我们全局唯一即可。query
没有when
和then
的部分
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))
endrule "rule_person_name_starts_with"
when
$p: Person($age:age < 18)
personNameStartsWith("张";
) // 此处多个参数使用 , 分割,并且最后必须以 ;
结尾
then
System.out.println("在rule中使用query");
end
【drools中query的使用】如果出现了如下异常`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
推荐阅读
- 投稿|RNG重赛始末
- Android中三种创建监听器的方法
- Windows 8系统应用商店中安装的软件缓存怎样清除
- Win8系统电脑中的文件怎样完成迅速反选设置【图】
- 客户沟通中的常见错误(如何不挫败客户)
- 时间复杂度和空间复杂度
- 中间件|Redis从入门到精通
- 汽车|今日涨幅榜冠军居然是中通客车 | 5月16日汽车制造企业上市公司股价日报
- 中国移动流量套餐攻略,用最少的钱买最多的流量
- 在H5 App中实现自定义Token的注意事项