drools中query的用法小結(jié)
一、背景
我們知道在drools
中是存在工作內(nèi)存
的,我們的Fact
對象會加入到工作內(nèi)存中,同時(shí)我們自己也可以在drl
文件中使用insert/modify/update/delete
等方法,修改工作內(nèi)存中對象的,那么我們怎么查詢修改之后的工作內(nèi)存的值呢?而drools
的query
可以幫助我們實(shí)現(xiàn)這個(gè)功能。
二、需求
1、無參數(shù)query的使用
2、有參數(shù)query的使用
3、java代碼中openLiveQuery
的使用
4、rule中使用query
三、前置需求
1、query的語法結(jié)構(gòu)
query queryName(參數(shù)列表) end
注意事項(xiàng):
query的名字
在同一個(gè)KIE base的所有包中必須要唯一
,一般情況下我們?nèi)治ㄒ患纯伞?code>query沒有when
和then
的部分
2、java中如何獲取query的結(jié)果
1、通過getQueryResults獲取
QueryResults queryResults = kieSession.getQueryResults("query的名字",可選參數(shù)類表);
通過這種方式getQueryResults
獲取到的結(jié)果只會獲取一次,如果工作內(nèi)存中的數(shù)據(jù)發(fā)生了變化,則不會自動感知到。
2、通過openLiveQuery獲取
kieSession.openLiveQuery("query的名字", new Object[]{可選參數(shù)}, new ViewChangedEventListener() { @Override public void rowInserted(Row row) {} @Override public void rowDeleted(Row row) { } @Override public void rowUpdated(Row row) {} });
通過這種方式openLiveQuery
是可以實(shí)時(shí)獲取到結(jié)果的,當(dāng)工作內(nèi)存中的數(shù)據(jù)發(fā)生變化,這個(gè)地方是可以感知到的。
四、實(shí)現(xiàn)
此處只列出部分核心代碼,一些無關(guān)的代碼不列出。
1、無參數(shù)query的使用
1、drl文件編寫
// 不帶參數(shù)的查詢 query "query01" // 注意這個(gè)地方的 $p,java代碼中需要用到 $p: Person(age < 18) end
2、java文件編寫
// 不帶參數(shù)的query查詢 QueryResults queryResults = kieSession.getQueryResults("query01"); queryResults.iterator().forEachRemaining(row -> { // 那么這個(gè)地方的 $p 是怎么來的呢?其實(shí)是我們自己編寫的drl query中寫的 Person person = (Person) row.get("$p"); log.info("query01從工作內(nèi)存中獲取的query: {}", person); });
2、有參數(shù)query的使用
1、drl文件編寫
// 帶參數(shù)的查詢 query query02(Integer $age) $p: Person(age < $age) end
2、java文件編寫
// 不帶參數(shù)的query查詢 // 帶參數(shù)的query查詢 queryResults = kieSession.getQueryResults("query02", 20); queryResults.iterator().forEachRemaining(row -> { Person person = (Person) row.get("$p"); log.info("query02從工作內(nèi)存中獲取的query: {}", person); });
3、java代碼中openLiveQuery的使用
1、drl文件編寫
// 帶參數(shù)的查詢-查詢工作內(nèi)存Person對象的age的值小于外部傳遞進(jìn)來的$age值 query query02(Integer $age) $p: Person(age < $age) end // 定義一個(gè)規(guī)則,當(dāng)規(guī)則內(nèi)存中的Person的age小于18時(shí),直接年齡+1 rule "rule_test_live_query_in_java" no-loop true when $p: Person($age:age < 18) then modify($p){ // 此處修改了工作內(nèi)存中age對象的值 setAge($p.getAge() + 1) } System.out.println("更新來規(guī)則內(nèi)存中Person["+$p.getName()+"]的age:["+$p.getAge()+"]值"); end
解釋:
1、定義查詢query02
查詢工作內(nèi)存中的對象。
2、rule_test_live_query_in_java
里面存在一個(gè) modify($p)
這個(gè)操作會導(dǎo)致更新工作內(nèi)存中對象的值。
3、no-loop true
表達(dá)的是當(dāng)前規(guī)則是否可以多次執(zhí)行,就我們定義的這個(gè)規(guī)則,如果修改后的age<18
那么可能還會導(dǎo)致規(guī)則的重新出發(fā),加了no-loop true
則只會觸發(fā)一次。
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()); // 實(shí)時(shí)查詢 kieSession.openLiveQuery("query02", new Object[]{20}, new ViewChangedEventListener() { @Override public void rowInserted(Row row) { Person person = (Person) row.get("$p"); log.info("實(shí)時(shí)查詢-query02向工作內(nèi)存中插入Person: {}", person); } @Override public void rowDeleted(Row row) { Person person = (Person) row.get("$p"); log.info("實(shí)時(shí)查詢-query02向工作內(nèi)存中刪除Person: {}", person); } @Override public void rowUpdated(Row row) { Person person = (Person) row.get("$p"); log.info("實(shí)時(shí)查詢-query02向工作內(nèi)存中更新Person: {}", person); } }); Person person1 = new Person("張三", 16); kieSession.insert(person1); kieSession.fireAllRules(); kieSession.dispose(); }
解釋:
1、此處先使用了openLiveQuery
查詢。
2、讓后向工作內(nèi)存中insert(person1)
,并且觸發(fā)了所有的規(guī)則fireAllRules
。
3、輸出結(jié)果
10:08:54.415 [main] INFO com.huan.drools.querys.DroolsLiveQueryApplication - 實(shí)時(shí)查詢-query02向工作內(nèi)存中插入Person: Person(name=張三, age=16)
更新來規(guī)則內(nèi)存中Person[張三]的age:[17]值
10:08:54.420 [main] INFO com.huan.drools.querys.DroolsLiveQueryApplication - 實(shí)時(shí)查詢-query02向工作內(nèi)存中更新Person: Person(name=張三, age=17)
可以看到,openLiveQuery
實(shí)時(shí)查詢到了工作內(nèi)存中變更的對象。
4、rule中使用query
drl
文件編寫
// 定義一個(gè)查詢,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("張";) // 此處多個(gè)參數(shù)使用 , 分割,并且最后必須以 ; 結(jié)尾 then System.out.println("在rule中使用query"); end
如果出現(xiàn)了如下異常Query's must use positional or bindings, not field constraints: "張" : [Rule name='rule_person_name_starts_with']
,這個(gè)是因?yàn)槲覀冊?code>rule中調(diào)用query
時(shí),參數(shù)沒有以;
結(jié)尾。正確用法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
到此這篇關(guān)于drools中query的使用的文章就介紹到這了,更多相關(guān)drools query使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot過濾器如何獲取POST請求的JSON參數(shù)
這篇文章主要介紹了SpringBoot過濾器如何獲取POST請求的JSON參數(shù)操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08Java?Stream排序的實(shí)現(xiàn)方式面試精講
這篇文章主要為大家介紹了Java?Stream排序的實(shí)現(xiàn)方式面試精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09springboot jackson自定義序列化和反序列化實(shí)例
這篇文章主要介紹了spring boot jackson自定義序列化和反序列化實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10spring自定義注解實(shí)現(xiàn)攔截器的實(shí)現(xiàn)方法
本篇文章主要介紹了spring自定義注解實(shí)現(xiàn)攔截器的實(shí)現(xiàn)方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08詳解Java使用雙異步后如何保證數(shù)據(jù)一致性
這篇文章主要為大家詳細(xì)介紹了Java使用雙異步后如何保證數(shù)據(jù)一致性,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以了解下2024-01-01Java中l(wèi)ong類型與Long類型的區(qū)別和大小比較詳解
這篇文章主要給大家介紹了Java中l(wèi)ong類型與Long類型區(qū)別和大小比較的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11jasypt 集成SpringBoot 數(shù)據(jù)庫密碼加密操作
這篇文章主要介紹了jasypt 集成SpringBoot 數(shù)據(jù)庫密碼加密操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11