首页 > 解决方案 > 有没有办法在drools中使用基于规则LHS的休眠插入事实

问题描述

我是新来的drools。我找到了根据文件中的规则自动从数据库中插入事实的lhs方法drl

如果有这样的规定,

    1: rule "simple rule"
    2:   when
    3:     Student( name == "Andy" )
    4:   then
    5: end

然后我从db使用中发现了事实hibernate

    StudentRepository.findByName("Andy");

但是,我不知道如何lhs在代码中使用该规则。请让我知道有一种方法以及如何做到这一点。

我几乎浪费了两个星期来做这件事......

添加我的代码) OnDemandMessageRuleUnit.java

package com.joel.messageRule.service;

import com.joel.messageRule.model.Daybook;
import com.joel.messageRule.model.Member;
import com.joel.messageRule.repositories.DaybookRepository;
import com.joel.messageRule.repositories.MemberRepository;
import lombok.Getter;
import org.kie.api.runtime.rule.DataSource;
import org.kie.api.runtime.rule.RuleUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

@Getter
@Component
public class OnDemandMessageRuleUnit implements RuleUnit {
    private DataSource<Member> members;
    private DataSource<Daybook> daybooks;
    private MemberRepository memberRepository;
    private DaybookRepository daybookRepository;
    private final Logger logger = LoggerFactory.getLogger(OnDemandMessageRuleUnit.class);

    public OnDemandMessageRuleUnit(MemberRepository memberRepository, DaybookRepository daybookRepository){
        this.memberRepository = memberRepository;
        this.daybookRepository = daybookRepository;
        this.members = DataSource.create();
        this.daybooks = DataSource.create();
    }

    @Override
    public void onStart() {
        // in this part i want to insert daybook objects which meet the condition written as rule lhs to data source or kiesession 
        logger.info("OnDemandMessageRuleUnit Started");
        for(Member m:members){
            List<Daybook> daybookList = m.getDaybooks();
            if(!daybookList.isEmpty()){
                for(Daybook d:daybookList){
                    daybooks.insert(d);
                }
            }
        }
    }

    @Override
    public void onEnd() {
        logger.info("OnDemandMessageRuleUnit Ended");
        try{
            for(Member m:members){
                memberRepository.save(m);
            }
            for(Daybook d:daybooks){
                daybookRepository.save(d);
            }
        }
        catch (NullPointerException e){
            e.printStackTrace();
            throw e;
        }
        finally {

        }
    }
}

恭维消息.drl

package com.joel.messageRule.service
unit OnDemandMessageRuleUnit

import java.lang.Number;
import com.joel.messageRule.model.*;
import org.slf4j.Logger;

rule "complimentMessage"
    dialect "mvel"
    when
        $receiver : Member(cumulativeDaybookRecord >= 3) from members
    then
        logger.info($receiver.getName() + "님에게 칭찬 메시지를 전송하였습니다.");
end

因此,我从规则或生产内存或节点内存中读取 Member(cumulativeDaybookRecord >= 3),查询“select * from Member wherecumulativeDaybookRecord >= 3”并将结果插入工作内存

标签: droolskiekogito

解决方案


你在正确的轨道上,但你RuleUnit需要一些调整。

RuleUnit 的目的,在我们在这里使用它的方式中,是以编写规则的人不需要了解如何从数据库中获取成员的方式提供成员。您的 RuleUnit 只是缺少该getMembers()方法才能使您的规则起作用。

你的规则是这样说的:

$receiver : Member(cumulativeDaybookRecord >= 3) from members

这是不打算做的select * from members where cumulativeDaybookRecord >= 3select * from members当 Drools 评估是否应该触发规则时,这将执行一个然后在内存中应用累积日记记录过滤器。这样,您可以为 >= 3 设置一条规则,为 == 0 设置另一条规则,依此类推,这些规则都适用于同一组成员。

实际上,这取决于您如何定义您public Datasource<Member> getMembers()尚未实现的方法。这是使一组成员可用于您的规则的逻辑。您可以使用 hibernate 以任何方式实现它,只要它产生成员实例的集合即可。但是,该方法不接受任何参数。

如果您将过滤器应用于数据库查询,那么 RuleUnit 是错误的模式。RuleUnit 作为数据源的想法是它为您提供数据集合,然后您可以针对该数据编写多个规则。因此,您可以针对不同的累积日记记录量、成员姓名、加入日期或其他任何内容编写规则——所有这些都使用相同的数据源。其他 RuleUnit 方法将允许您使用正确的启动/停止处理安全地包装该数据库交互,这对于连接或事务管理很有用。

但是,如果您确实在查询本身上使用不同的过滤器执行多个数据库查询,那么这不是适合您使用的结构。您可能不得不像 Thilakar Raj 在他的回答中建议的那样对存储库进行实际调用(尽管我非常不建议在这样的规则中进行数据库调用,因为 Drools 如何评估规则。)如果问题是编写规则的人不是程序员,那么答案可能是为存储库编写一个自定义包装器,使用特殊方法应用过滤器或预制过滤器,然后将其传递工作内存中。


推荐阅读