好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

drools中query的用法小结

一、背景

我们知道在 drools 中是存在 工作内存 的,我们的 Fact 对象会加入到工作内存中,同时我们自己也可以在 drl 文件中使用 insert/modify/update/delete 等方法,修改工作内存中对象的,那么我们怎么查询修改之后的工作内存的值呢?而 drools 的 query 可以帮助我们实现这个功能。

二、需求

1、无参数query的使用
2、有参数query的使用
3、java代码中 openLiveQuery 的使用
4、rule中使用query

三、前置需求

1、query的语法结构

?

1

2

query queryName(参数列表)

end

注意事项:

query的名字 在同一个KIE base的所有包中 必须要唯一 ,一般情况下我们全局唯一即可。 query 没有 when 和 then 的部分

2、java中如何获取query的结果

1、通过getQueryResults获取

?

1

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

通过这种方式 getQueryResults 获取到的结果只会获取一次,如果工作内存中的数据发生了变化,则不会自动感知到。

2、通过openLiveQuery获取

?

1

2

3

4

5

6

7

8

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文件编写

?

1

2

3

4

5

// 不带参数的查询

query "query01"

     // 注意这个地方的 $p,java代码中需要用到

     $p: Person(age < 18)

end

2、java文件编写

?

1

2

3

4

5

6

7

// 不带参数的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文件编写

?

1

2

3

4

// 带参数的查询

query query02(Integer $age)

     $p: Person(age < $age)

end

2、java文件编写

?

1

2

3

4

5

6

7

// 不带参数的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文件编写

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

// 带参数的查询-查询工作内存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文件编写

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

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 文件编写

?

1

2

3

4

5

6

7

8

9

10

11

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

如果出现了如下异常 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测试数据/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

到此这篇关于drools中query的使用的文章就介绍到这了,更多相关drools query使用内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

原文链接:https://HdhCmsTestcnblogs测试数据/huan1993/p/16277940.html

查看更多关于drools中query的用法小结的详细内容...

  阅读:19次