持久感知 KieSession 在事务期间不使用悲观锁

2024-04-20

我在用Drools with 春季启动2.3 我已经实现了持久意识KieSession,其中MySQL用于存储会话。我已经成功集成了默认的EntityManagerFactorySpring Boot 与 Drools 的结合,但我的问题是事务。默认情况下,Drools 在事务期间使用乐观锁,但它也允许我们使用悲观锁,这正是我想要的。现在,在触发规则时,Drools 使用以下查询保留/更新 MySQL 中的 KieSession:

update SessionInfo set lastModificationDate=?, rulesByteArray=?, startDate=?, OPTLOCK=? where id=? and OPTLOCK=?

现在,如果我不使用事务,上面的语句会执行两次@Transactional方法中的注释,如果@Transactional使用后,上述语句在触发规则后仅执行一次。

现在,如果我手动更改 OPTLOCK 字段的值,则 Drools 会引发异常:

javax.persistence.OptimisticLockException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [org.drools.persistence.info.SessionInfo#1]

其次是:

Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [org.drools.persistence.info.SessionInfo#1]

由于此处的文本长度限制,我无法发布整个 Stacktrace。整个堆栈跟踪可以在以下位置查看这个 GitHub 项目 https://github.com/samimaftabahmed/spring-drools-persistence.

我不确定 Drools 是否使用环境中定义的悲观锁。关于我的会话实现,我想要一个KieSession因为我使用 KieSession 作为Bean.

下面是我的实现:

配置类:

@Configuration
public class DynamicDroolsConfig {

    private KieServices kieServices;
    private KieFileSystem kieFileSystem;

    @Autowired
    private PersistentSessionDAO persistentSessionDAO;
    @PersistenceUnit
    private EntityManagerFactory entityManagerFactory;
    @Autowired
    private PlatformTransactionManager platformTransactionManager;


    @PostConstruct
    private void init() {
        this.kieServices = KieServices.Factory.get();
        this.kieFileSystem = kieServices.newKieFileSystem();
    }

    @Bean
    public KieServices getKieServices() {
        return this.kieServices;
    }

    @Bean
    public KieContainer getKieContainer() {
        kieFileSystem.write(ResourceFactory.newClassPathResource("rules/rules.drl"));
        final KieRepository kieRepository = kieServices.getRepository();
        kieRepository.addKieModule(kieRepository::getDefaultReleaseId);
        KieBuilder kb = kieServices.newKieBuilder(kieFileSystem).buildAll();
        KieModule kieModule = kb.getKieModule();
        return kieServices.newKieContainer(kieModule.getReleaseId());
    }

    @Bean
    public KieFileSystem getFileSystem() {
        return kieFileSystem;
    }

    @Bean
    public KieSession kieSession() {
        List<SessionInfo> sessionDetails = persistentSessionDAO.getSessionDetails();

        if (sessionDetails.size() == 0) {
            return kieServices.getStoreServices().newKieSession(getKieContainer().getKieBase(), null, getEnv());
        } else {
            return kieServices.getStoreServices().loadKieSession(sessionDetails.get(0).getId(), getKieContainer().getKieBase(), null, getEnv());
        }
    }

    private Environment getEnv() {
        Environment env = kieServices.newEnvironment();
        env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, entityManagerFactory);
        env.set(EnvironmentName.TRANSACTION_MANAGER, platformTransactionManager);
        env.set(EnvironmentName.USE_PESSIMISTIC_LOCKING, true);
        env.set(EnvironmentName.USE_PESSIMISTIC_LOCKING_MODE, LockModeType.PESSIMISTIC_FORCE_INCREMENT.name());
        return env;
    }
}

控制器类:

@RestController
public class MyController {

    @Autowired
    private KieSession kieSession;

    @Transactional
    @GetMapping("fire-person")
    public void firePerson() {
        Person person = new Person();
        person.setName("Christy");
        kieSession.insert(person);
        kieSession.fireAllRules();
    }
}

事实类

public class Person implements Serializable {

    private String name;
    private int age;
    private String gender;
    private String toCompareName;
    private String toCompareGender;

    // getters and setters
}

存储库接口:

public interface DroolsSessionRepository extends JpaRepository<SessionInfo, Long> {
}

服务等级:

@Service
public class PersistentSessionDAO {

    @Autowired
    private DroolsSessionRepository droolsSessionRepository;

    public List<SessionInfo> getSessionDetails() {
        return droolsSessionRepository.findAll();
    }
}

跑步者类别:

@EntityScan(basePackages = {"com.sam.springdroolspersistence.entity", "org.drools.persistence.info"})
@EnableJpaRepositories
@SpringBootApplication
public class SpringDroolsPersistenceApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringDroolsPersistenceApplication.class, args);
    }
}

使用的 Drools 依赖项:

        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-persistence-jpa</artifactId>
            <version>${drools-version}</version>
        </dependency>

        <dependency>
            <groupId>org.kie</groupId>
            <artifactId>kie-spring</artifactId>
            <version>${drools-version}</version>
        </dependency>

        <dependency>
            <groupId>org.jbpm</groupId>
            <artifactId>jbpm-persistence-jpa</artifactId>
            <version>${drools-version}</version>
        </dependency>

代码实现也可以在这个 GitHub 项目 https://github.com/samimaftabahmed/spring-drools-persistence。任何形式的帮助/建议将不胜感激。谢谢。


悲观锁仅在 JBPM 中实现,请参见here https://github.com/lucamolteni/jbpm/blob/6a0cc1ff1874563afefe635b5c63e8b6278b007a/jbpm-test-coverage/src/test/java/org/jbpm/test/functional/task/PessimisticLockTasksServiceTest.java#L94

Drools 持久化中没有这样的功能,SessionInfo将始终使用基于 JPA 的 OptimisticLocking@Version注解。

如果您需要此类功能,请在 Drools 上提交功能请求Jira https://issues.redhat.com/secure/Dashboard.jspa

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

持久感知 KieSession 在事务期间不使用悲观锁 的相关文章

随机推荐

  • 将静态宽度垂直子菜单置于动态水平菜单下方

    我已经在这个问题上呆了好几个小时了 我可以找到我想要的各个组成部分 但我似乎无法将它们组合在一起 我遇到的问题是我无法让静态宽度子菜单以它们派生的 li 项目为中心 如果这些父 li 项目具有静态宽度 这应该很容易 但我想根据页面的宽度动态
  • compileSdkVersion 'Google Inc.:Google APIs:23' 和compileSdkVersion 23 之间有什么区别

    在 Gradle build 文件中 我看到一些项目使用 compileSdkVersion Google Inc Google APIs 23 有些只是使用号码 compileSdkVersion 23 两者有什么区别 后一种对于绝大多数
  • Java有using语句吗?

    Java有没有可以在hibernate中打开会话时使用的using语句 在 C 中 它类似于 using var session new Session 因此该对象超出范围并自动关闭 Java 7 推出自动资源块管理 http www in
  • 如何在 fs2 中“拆分”流?

    我想做这样的事情 def splitStream F A stream fs2 Stream F A split A gt B Stream F A Stream F B stream stream map split 但这不起作用 因为它
  • Git 分支从哪里开始以及它的长度是多少?

    我时不时地被问到 git 上的某个分支在什么提交上启动 或者是否在特定分支上创建了某个提交 分支的终点非常清楚 那就是分支标签所在的位置 但是 从哪里开始呢 简单的答案是 在我们的提交中created那个分支 但据我现在所知 这些信息在第一
  • np.linspace 和 np.arange 有什么区别?

    我一直用np arange 我最近遇到np linspace 我想知道它们之间到底有什么区别 查看他们的文档 np arange https numpy org doc 1 18 reference generated numpy aran
  • 如何从 2 个列表中确定最佳组合

    我正在寻找一种方法来使团体中的人员达到最佳组合 让我概述一下情况 假设我们有 A B C 和 D 此外 我们还有组 1 2 3 4 和 5 两者都是示例 可以更少或更多 每个人都给彼此打分 例如 A 对 B 的评分为 3 C 对 C 的评分
  • Objective-C 中的类对象和实例变量

    我很难理解这个概念 我直接引用书中的一句话 类对象还继承自层次结构中位于其上方的类 但因为它们没有实例变量 只有实例有 所以它们只继承方法 如果我错了 请纠正我 但类对象将是这样的 NSString aString NSString all
  • AWS Elasticsearch 和 CORS

    我正在试用 AWS Elasticsearch 服务 https aws amazon com elasticsearch service https aws amazon com elasticsearch service 设置非常简单
  • 根据 C++ 标准,int 变量是对象吗?

    下面您将找到 C 标准中对象的定义 介绍对象 1 http eel is c draft intro object 1 C 程序中的构造创建 销毁 引用 访问和 操纵物体 一个object由定义 6 1 创建 由新表达 8 3 4 隐式更改
  • SFSafariViewController PresentViewController 动画

    当我打电话时presentViewController mySafariViewController animated true completion nil 视图始终像导航控制器一样从右侧进行动画处理 我尝试打电话mySafariView
  • 如何在 postgresql 中更改类型并删除值[重复]

    这个问题在这里已经有答案了 我发现了如何增加价值TYPE 但我怎样才能从中删除价值呢 例如我有TYPE with enum values A B C 如何去除 C 要从枚举 enum test 中删除值 val1 您可以使用 DELETE
  • 从 Matlab 中的时钟图像获取时间 - 图像处理

    时钟 http img710 imageshack us img710 2623 circlock jpg http img710 imageshack us img710 2623 circlock jpg 我不知道如何确定时钟指针的顶部
  • iOS >> ShareKit >> 选择所需的共享服务

    我已经在我的应用程序中实现了 ShareKit 我同意它的默认工作方式 但我希望控制可供用户选择的服务 更具体地说 我不想处理默认嵌入的所有服务 而只想处理 Facebook Twitter 和 Mail 我在 ShareKit 文件中的哪
  • Git 格式补丁输出在单个文件中

    如何将命令 format patch 的输出定向到单个文件 stdout gt 文件名
  • 嵌入公共 Facebook 页面的活动源,无需强制用户登录/允许

    这与之前多次提出的问题类似 但无论我读什么 我仍然很困惑 我有一个公共 Facebook 页面 例如 White Collar 我需要将其活动源嵌入到我的 Android 应用程序中 我了解如何获取应用程序 ID 和应用程序秘密 但我不了解
  • 如何处理Junits中Maven和Intellij之间的相对路径

    我有一个带有模块的 Maven 项目 myProject pom xml myModule pom xml foo bar txt 考虑一个 JunitmyModule需要打开哪个bar txt 对于 maven basedir 是模块目录
  • g++:找不到文件

    我最近一直在开发一个程序 该程序从 Java 程序编译并运行 C 程序 我已经让一切基本正常工作 或至少据我所知 但后来我注意到一些东西被打印到错误流中 cdog5000 srv3 java Xmx50m jar main2 jar Run
  • Python 中首选 `if x:` 或 `if x != 0:` 哪一个?

    假如说x是一个整数 构造if x 功能上与if x 0 在Python中 某些语言的风格指南明确禁止前者 例如 ActionScript Flex 的风格指南指出 您永远不应该为此类事情隐式地将 int 强制转换为 bool Python
  • 持久感知 KieSession 在事务期间不使用悲观锁

    我在用Drools with 春季启动2 3 我已经实现了持久意识KieSession 其中MySQL用于存储会话 我已经成功集成了默认的EntityManagerFactorySpring Boot 与 Drools 的结合 但我的问题是