当前位置: 首页 > 后端技术 > Java

drools中query的使用

时间:2023-04-01 21:34:22 Java

一、背景我们知道drools中有工作内存,我们的Fact对象会被添加到工作内存中,我们也可以在drl文件中使用insert/modify/update/delete等对于修改工作内存中对象的方法,那么我们如何查询修改后的工作内存中的值呢?drools的查询可以帮助我们实现这个功能。二、需求1、不带参数的query的使用2、带参数的query的使用3、java代码中openLiveQuery的使用4、rules中query的使用三、前置要求1、query查询queryName(参数列表)的语法结构endnote注意事项:查询的名称在同一个KIEbase的所有包中必须是唯一的。一般来说,我们可以是全球独一无二的。Query没有when和thenpart2.java中如何获取query的结果1.通过getQueryResults获取QueryResultsqueryResults=kieSession.getQueryResults("queryname",optionalparameterclasstable);这样getQueryResults得到的结果只会被取一次,如果workingmemory中的数据发生了变化,是不会自动感知到的。2、通过openLiveQuery.openLiveQuery("queryname",newObject[]{optionalparameter},newViewChangedEventListener(){@OverridepublicvoidrowInserted(Rowrow){}@OverridepublicvoidrowDeleted(Rowrow){}获取kieSession@OverridepublicvoidrowUpdated(Rowrow){}});这样openLiveQuery就可以实时获取结果,当工作内存中的数据发生变化时,这个地方是可以感知到的。4.实现这里只列出了部分核心代码,一些无关的代码没有列出。一、不带参数查询的使用1、编写drl文件//查询不带参数的query"query01"//注意这个地方的$p,java代码中需要$p:Person(age<18)end2,javaFilewriting//queryquery不带参数QueryResultsqueryResults=kieSession.getQueryResults("query01");queryResults.iterator().forEachRemaining(row->{//那么$p是怎么来的?其实Personwritteninthedrlquerywrittenperson=(Person)row.get("$p");log.info("query01从工作内存中获取:{}",person);});2、使用带参数的query1,写drlfile//queryquerywithparametersquery02(Integer$age)$p:Person(age<$age)end2,写java文件//queryquerywithoutparameters//withParameterqueryqueryResults=kieSession.getQueryResults("query02",20);queryResults.iterator().forEachRemaining(row->{Personperson=(Person)row.get("$p");log.info("query02查询从工作内存中获取:{}",person);});三、openLiveQuery在java代码中的使用1.写drl文件//带参数查询-查询工作内存中Person对象的age值小于外部查询中传入的$age值query02(Integer$age)$p:Person(age<$age)end//定义一个规则,当Person的年龄在规则内存中小于18时,直接age+1rule"rule_test_live_query_in_java"no-looptruewhen$p:Person($age:age<18)thenmodify($p){//这里age对象的值在修改工作内存setAge($p.getAge()+1)}System.out.println("更新规则Person["+$p.getName()+"]在内存中的年龄:["+$p.getAge()+"]值");end解释:1.定义queryquery02查询工作内存中的对象2.rule_test_live_query_in_java中有一个modify($p)这个操作会导致工作内存中对象的值被更新。3.no-looptrue表示当前规则是否可以多次执行。对于我们定义的规则,如果修改后的年龄<18,也可能导致规则重新启动。添加no-looptrue只会触发一次。2.Java文件编写publicstaticvoidmain(String[]args){KieServiceskieServices=KieServices.get();KieContainerkieContainer=kieServices.getKieClasspathContainer();KieSessionkieSession=kieContainer.newKieSession("query-ksession");kieSession。addEventListener(新的DebugRuleRuntimeEventListener());kieSession.addEventListener(newDebugAgendaEventListener());kieSession.addEventListener(newDebugProcessEventListener());//实时查询kieSession.openLiveQuery("query02",newObject[]{20},newEventViewChangered(){@OverridepublicvoidrowInserted(Rowrow){Personperson=(Person)row.get("$p");log.info("实时查询-query02将Person插入工作内存:{}",person);}@OverridepublicvoidrowDeleted(Rowrow){Personperson=(Person)row.get("$p");log.info("实时查询-query02从工作记忆中删除Person:{}",person);}@OverridepublicvoidrowUpdated(Rowrow){Personperson=(Person)row.get("$p");log.info("实时查询-query02更新工作记忆中的Person:{}",person);}});Personperson1=newPerson("张三",16);kieSession.insert(person1);kieSession.fireAllRules();kieSession.dispose();}解释:1.这里使用了OpenLiveQuery查询2,让insert(person1)在backwardworkingmemory中,触发所有规则fireAllRules。3.输出结果10:08:54.415[main]INFOcom.huan.drools.querys.DroolsLiveQueryApplication-real-timequery-query02InsertPersonintotheworkingmemory:Person(name=ZhangSan,age=16)更新为规则内存Person[ZhangSan]'sage:[17]value10:08:54.420[main]INFOcom.huan.drools.querys.DroolsLiveQueryApplication-real-timequery-query02UpdatePersonintheworkingmemory:Person(name=ZhangSan,age=17)可见openLiveQuery实时查询了工作内存中发生变化的对象。###4.使用规则中的querydrl文件编写//定义查询,Person#name需要以$prefix开头querypersonNameStartsWith(String$prefix)Person(name.startsWith($prefix))endrule"rule_person_name_starts_with"when$p:Person($age:age<18)personNameStartsWith("Zhang";)//这里的多个参数用分隔,必须以;结尾thenSystem.out.println("usequeryinrule");end如果出现以下异常`Query'smustusepositionalorbindings,notfieldconstraints:"Zhang":[Rulename='rule_person_name_starts_with'],这是因为当我们在规则中调用查询,参数不以;结尾。正确使用personNameStartsWith("Zhang";)`?personNameStartsWith("Zhang";)和personNameStartsWith("Zhang";)是不同的。这?符号表示查询是拉取的,一旦返回结果,你将不会收到进一步的结果,因为底层数据发生变化五、完整代码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