Activiti 6中的可插拔持久性

在过去的几年中,我们经常听到(来自社区和我们的客户)关于如何将Activiti的持久性逻辑从关系数据库交换到其他内容的请求。 当我们宣布Activiti 6时, 我们做出的承诺之一就是我们将实现这一目标。

深入研究Activiti引擎代码的人会知道,这是认真的重构,因为持久性代码与常规逻辑紧密结合。 基本上,在Activiti v5中,有:

  • 实体类 :这些实体类包含数据库中的数据。 通常,一个数据库行是一个实体实例
  • EntityManager :这些类将与实体相关的操作分组(查找,删除等)
  • DbSqlSession :使用MyBatis的低级操作(CRUD)。 还包含命令持续时间缓存,并管理数据到数据库的刷新。

版本5中的问题如下:

  • 没有接口。 一切都是一类,因此替换逻辑变得非常困难。
  • 整个代码库中到处都使用了低级DbSqlSession。
  • 很多关于实体的逻辑载的实体类 。 例如,查看TaskEntity complete方法。 您不必是Activiti专家即可了解这不是一个不错的设计:
    • 触发一个事件

现在不要误会我的意思。 v5代码将我们带到了很远的地方,并为世界各地许多出色的功能提供了支持。 但是,当涉及到交换持久层时……这并不值得骄傲。

并且可以肯定,我们可以闯入版本5代码(例如,通过用响应于那里使用的方法/查询名称的自定义东西换出DbSqlSession),但这仍然不是很好的设计方法和非常像关系数据库。 而且这不一定与您可能使用的数据存储技术匹配。

不, 对于版本6,我们希望正确执行 。 而且,天哪……我们知道这将需要大量工作……但是它的工作量超出了我们的想象(只需查看过去几周内v6分支上的提交 )。 但是我们做到了……最终的结果很美 (我有偏见,是的)。 因此,让我们看一下v6中的新架构(请原谅我的powerpoint图片。我是编码人员,而不是设计师!):

屏幕截图-2015-09-17-17.14.00

因此,在v5中没有接口的地方,在v6中到处都有接口。 上面的结构适用于引擎中的所有Entity类型 (当前为25个左右)。 因此,例如对于TaskEntity ,有一个TaskEntityImpl , TaskEntityManager , TaskEntityManagerImpl , TaskDataManager和TaskDataManagerImpl类(是的,我知道,他们仍然需要javadoc)。 这适用于所有实体

让我解释一下上图:

  • EntityManager :这是与数据有关的所有其他代码都可以与之通信的接口。 当涉及特定实体类型的数据时,它是唯一的入口点。
  • EntityManagerImplEntityManager类的实现。这些操作通常是高层的,并且同时执行多项操作。 例如,执行删除可能还会删除任务,作业,identityLinks等并触发相关事件。 每个EntityManager实现都有一个DataManager。 每当需要持久性存储中的数据时,它就使用此DataManager实例获取或写入相关数据。
  • DataManager:此接口包含“低级”操作。 通常包含针对其管理的实体类型的CRUD方法以及需要特定用例数据时的特定查找方法
  • DataManagerImpl :DataManager接口的实现。 包含实际的持久性代码。 在v6中,这是唯一现在使用DbSqlSession类通过MyBatis与数据库进行通信的类。 通常,这是您要换出的班级。
  • 实体 :数据接口。 包含getter和setter。
  • EntityImpl :上述接口的实现。 在Activiti v6中,这是常规的pojo,但是该界面允许您切换到其他技术,例如带有spring-dataj,JPA,…(使用批注)的Neo4。 没有它,如果默认实现在您的持久性技术上不起作用,则需要包装/拆开实体。

合并

将所有操作移入接口可以使我们清楚地了解在代码库中分布了哪些方法。 例如,您是否知道至少有五种不同的方法来删除执行(名为“删除”,“删除”,“销毁”等)? 他们所做的几乎相同,但有细微的差别。 有时甚至一点都不微妙。

过去几周的许多工作包括将所有这些逻辑整合为一种方法。 现在,在当前的代码库中,只有一种方法可以执行某些操作。 对于想使用不同持久性技术的人来说,这非常重要。 使它们实现所有变体和微妙之处将是疯狂的。

内存中实现

为了证明持久层的可插入性,我制作了一个小的“内存中”原型。 这意味着,我们使用普通的旧式HashMaps代替关系数据库来将实体存储为{entityId,Entitys}。 然后查询成为if子句。

  • 可以在Github上找到代码: https : //github.com/jbarrez/activiti-in-mem-prototype

(有时在论坛上,人们问到仅在内存中运行Activiti会有多困难,对于那些不要求使用数据库的简单用例来说。现在,这不再困难了!谁知道……这个小原型如果人们喜欢,它可能会变成东西!)

  • 如预期的那样,我们用内存中的版本换出了DataManager实现,请参阅InMemoryProcessEngineConfiguration
@Overrideprotected void initDataManagers() {this.deploymentDataManager = new InMemoryDeploymentDataManager(this);this.resourceDataManager = new InMemoryResourceDataManager(this);this.processDefinitionDataManager = new InMemoryProcessDefinitionDataManager(this);this.jobDataManager = new InMemoryJobDataManager(this);this.executionDataManager = new InMemoryExecutionDataManager(this);this.historicProcessInstanceDataManager = new InMemoryHistoricProcessInstanceDataManager(this);this.historicActivityInstanceDataManager = new InMemoryHistoricActivityInstanceDataManager(this);this.taskDataManager = new InMemoryTaskDataManager(this);this.historicTaskInstanceDataManager = new InMemoryHistoricTaskInstanceDataManager(this);this.identityLinkDataManager = new InMemoryIdentityLinkDataManager(this);this.variableInstanceDataManager = new InMemoryVariableInstanceDataManager(this);this.eventSubscriptionDataManager = new InMemoryEventSubscriptionDataManager(this);}

这样的DataManager实现非常简单。 例如,请参阅InMemoryTaskDataManager ,它需要为TaskEntity实现数据检索/写入方法

public List<TaskEntity> findTasksByExecutionId(String executionId) {List<TaskEntity> results = new ArrayList<TaskEntity>();for (TaskEntity taskEntity : entities.values()) {if (taskEntity.getExecutionId() != null && taskEntity.getExecutionId().equals(executionId)) {results.add(taskEntity);}}return results;}

为了证明它是可行的,让我们进行部署,启动一个简单的流程实例,进行一些小任务查询并检查一些历史记录。 此代码与“常规” Activiti用法完全相同。

public class Main {public static void main(String[] args) {InMemoryProcessEngineConfiguration config = new InMemoryProcessEngineConfiguration();ProcessEngine processEngine = config.buildProcessEngine();RepositoryService repositoryService = processEngine.getRepositoryService();RuntimeService runtimeService = processEngine.getRuntimeService();TaskService taskService = processEngine.getTaskService();HistoryService historyService = processEngine.getHistoryService();Deployment deployment = repositoryService.createDeployment().addClasspathResource("oneTaskProcess.bpmn20.xml").deploy();System.out.println("Process deployed! Deployment id is " + deployment.getId());ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess");List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list();System.out.println("Got " + tasks.size() + " tasks!");taskService.complete(tasks.get(0).getId());System.out.println("Number of process instances = " + historyService.createHistoricProcessInstanceQuery().count());System.out.println("Number of active process instances = " + historyService.createHistoricProcessInstanceQuery().finished().count());System.out.println("Number of finished process instances = " + historyService.createHistoricProcessInstanceQuery().unfinished().count());}}

如果运行它,它可以为您提供这一切(非常快,因为它们全部在内存中!):

Process deployed! Deployment id is 27073df8-5d54-11e5-973b-a8206642f7c5Got 1 tasks!Number of process instances = 1Number of active process instances = 0Number of finished process instances = 1

在这个原型中,我没有添加事务语义。 这意味着,如果两个用户将同时完成同一用户任务,那么结果将是不确定的。 当然,您可能希望从Activiti API获得类似内存中事务的逻辑,但是我尚未实现。 基本上,您需要将所有接触的对象保留在一个小的缓存中,直到刷新/提交时间,然后在该位置进行一些锁定/同步。 当然,我确实接受拉取请求:)

下一步是什么?

好吧,这完全取决于您。 让我们知道您对此有何想法,请尝试一下!

我们与计划很快试用的社区成员/客户之一保持着密切联系。 但是我们当然也想自己玩这个游戏,我们正在寻找一个很酷的首选(我自己在Neo4j的心中仍然占有特殊的位置 ……这很适合交易)。

但是最重​​要的一点是:在Activiti v6中,现在可以干净地交换持久层。 我们为现在的外观感到自豪。 我们希望您也喜欢它!

翻译自: https://www.javacodegeeks.com/2015/09/pluggable-persistence-in-activiti-6.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/358359.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

src漏洞类型总结

本文转载于https://blog.csdn.net/qq_33942040/article/details/111831536 这三类存在漏洞可能更大 越他娘丑的站&#xff0c;越有可能存在洞。 Asp aspx 存在漏洞的可能更大 登陆口没得验证码的可能存在一,未授权访问 常见28种服务器或者中间协议未授权访问 易出现处 ①照片…

[LeetCode][JavaScript]Roman to Integer

Roman to Integer Given a roman numeral, convert it to an integer. Input is guaranteed to be within the range from 1 to 3999. https://leetcode.com/problems/roman-to-integer/ 罗马数字转阿拉伯数字。 从后往前扫&#xff0c;如果当前的数大于之前的数&#xff0c;加…

【APICloud系列|19】上架APPStore需要准备哪些材料?

前端时间用敏捷式开发平台开发了一款APP应用,应用名称我就不说啦,这篇文章主要讲述一下上架苹果应用商店APPStore需要准备哪些材料,有相关的困扰欢迎私信我。 一、上架流程 1. 注册苹果企业账号 2. 创建测试证书,发布证书 (使用Mac) 3. 使用xcode 上传应用到APP Store (…

Json注入

一、Json简介 JSON 是存储和交换文本信息的语法&#xff0c;是轻量级的文本数据交换格式。类似xml&#xff0c;但JSON 比 XML 更小、更快&#xff0c;更易解析。所以现在接口数据传输都采用json方式进行。JSON 文本的 MIME 类型是 “application/json”。 json语法 数据在名…

国行 lg g3 D858 刷 lg g3 D858hk 教程(备忘)

纯手打&#xff0c;转载请注明出处~ 刷机有风险&#xff0c;出现问题概不负责&#xff01; 本着自娱自乐的宗旨 &#xff0c;分享一下&#xff0c;出了问题不负责&#xff01; 准备的材料&#xff1a; 1&#xff0c;手机一枚&#xff08;废话&#xff09;国行lg g3 d858 2&am…

七夕(情人节)表白女朋友,程序员应该如何装一波13

很多小伙伴私信说程序员应该怎么表白女朋友,大神支个招,直接上代码。最近的.vbs或者.vbe表白真的很火,小伙伴们赶紧动起来。(废话少说,赶紧往下看) 代码一: msgbox("做我女粉丝好吗?")msgbox("房产证上写你名字")msgbox("孙叫兽")msgb…

渗透测试-验证码的爆破与绕过

【验证码机制原理】 客户端发起请求->服务端响应并创建一个新的SessionID同时生成随机验证码&#xff0c;将验证码和SessionID一并返回给客户端->客户端提交验证码连同SessionID给服务端->服务端验证验证码同时销毁当前会话&#xff0c;返回给客户端结果。 【客户端可…

java并发调用_Java并发教程–可调用,将来

java并发调用从Java的第一个发行版开始&#xff0c;Java的美丽之处之一就是我们可以轻松编写多线程程序并将异步处理引入我们的设计中。 Thread类和Runnable接口与Java的内存管理模型结合在一起&#xff0c;意味着可以直接进行线程编程。 但是&#xff0c;如第3部分所述&#x…

最近对项目代码做的一些更改和感想

最近对项目代码做了一些更改&#xff0c;主要的改动是对整个界面框架的改变&#xff0c;因为以前写代码的时候&#xff0c;为了完成功能&#xff0c;没有从上帝视角来思考软件的界面设计&#xff0c;完全是需要这个功能了&#xff0c;怎么可以做到&#xff1f;好&#xff0c;就…

CSS常见的四种垂直居中的方法

面试中不管是笔试题还是面试题,一般很容易被问到如何实现垂直水平居中,这里总结四种方法作为参考 (1)margin:auto法 css: div{ width: 400px; height: 400px; position: relative; border: 1px solid #465468; } img{ position: absolute; margin: auto; top: 0; left: 0; …

Linux下切换Python2和Python3的4种方法

本篇博文面向Linux用户&#xff0c;在Linux下(Ubuntu)下测试通过&#xff0c;Win用户嘛&#xff0c;…… 0x00 为什么需要有两个版本的Python Python2和Python3不兼容是每个接触过Python的开发者都知道的事&#xff0c;虽说Python3是未来&#xff0c;但是仍然有很多项目采用P…

异步EJB只是一个Gi头吗?

在之前的文章&#xff08; 此处和此处 &#xff09;中&#xff0c;我展示了当服务器负载沉重时&#xff0c;创建非阻塞异步应用程序可以提高性能。 EJB 3.1引入了Asynchronous批注&#xff0c;用于指定方法将在将来的某个时间返回其结果。 Javadocs声明必须返回void或Future 。…

常见的清除浮动的五种解决办法

方法一:使用带clear属性的空元素 在浮动元素后使用一个空元素如 <div class="clear"></div> 并在CSS中赋予 .clear{clear:both;} 属性即可清理浮动。亦可使用 <br class="clear" /> 或 <hr class="clear" /> …

Kali环境下安装python3

Kali环境下安装python3 参考&#xff1a; 由于kali环境下是自动安装了python 2.7&#xff0c;没有python3以上的版本&#xff0c;现在开始安装python 1. 先下载python3的tar包 进入这个目录&#xff1a; cd /usr/local/ 创建一个新文件夹python3&#xff1a; mkdir /usr/loc…

用汇编语言写的第一个DOS程序

今天整理电脑时&#xff0c;看到两三年前学习汇编语言时写的显示“Hello”的程序。不禁感叹那个时候学得如此用心&#xff0c;同样的功能&#xff0c;我竟然用了四种写法。现贴出源码&#xff0c;为了以后继续学习&#xff0c;也为了给初学者一点启发。(删掉注释了&#xff0c;…

对安卓应用进行加固签名,为上架各大应用市场做准备

上架安卓各大应用市场之前需要对自己的应用进行签名加固&#xff0c;签名是为了证明你是这个应用的开发者&#xff0c;软著也是一种方式&#xff0c;这是不做介绍&#xff0c;加固是为了从安全角度给安装包加一个保护层&#xff0c;防止被恶意破解及攻击。下面简单介绍一下签名…

ADO.Net 事务操作

DbTransaction转载于:https://www.cnblogs.com/lxf1117/p/4773742.html

docker安装pocbox(漏洞测试验证辅助平台)

PoCBox - 漏洞测试验证辅助平台 开发这个平台的初衷是帮助自己在漏洞挖掘测试中更加方便快捷的辅助自己进行漏洞验证。 一开始的想法是框架化、模块化&#xff0c;但是开发着开发着就发现有点累&#xff0c;于是采用了原始的方法去开发&#xff1a;原生JavaScriptPHP。 PoCBo…

内存映射获取行数_使用内存映射文件获取巨大的矩阵

内存映射获取行数总览 矩阵可能真的很大&#xff0c;有时甚至比您可以容纳在一个数组中的要大。 您可以通过具有多个数组来扩展最大大小&#xff0c;但这会使堆大小确实很大且效率低下。 一种替代方法是在内存映射文件上使用包装器。 内存映射文件的优点是它们对堆的影响很小&a…

大前端最强vscode教程(基础篇)

这段时间入职了一家外包公司的前端工程师岗位,前端编辑器用起来,前端一般会用到几个编译器,VScode、sublime text3、webstorm、Hbuid等,这里主要介绍VScode. 初次使用vscode时各种不适应,所有需要用到的功能貌似都需要单独安装插件才能用。这让很多初次使用vscode的朋友有…