低代码信创开发核心技术(三):MDA模型驱动架构及元数据系统设计

前言

写最后一篇文章的时候,我本人其实犹豫了半年,在想是否发布出这篇文章,因为可能会动了很多人的利益。所以这篇文章既是整个低代码信创开发的高度总结,也是最为精华的一部分,它点明了低代码中最为核心的技术。虽然你在读这篇文章的时候会有犹抱琵琶半遮面的感觉,但当你领悟之后,会发现原来低代码开发平台的建设是如此的简单。低代码前端设计模型,而设计出来的模型以元数据的方式又能驱动整个系统运行,读完你会发现实在是非常巧妙的设计。一旦拥有了这个设计思想下建立的系统,一个程序员一天做出一套管理系统不再是梦,而且运维和调整将变得极为简单、实时,管理系统将变得极为廉价,所以恕我不能详述具体实现的代码。信息化对于实现中华民族伟大复兴的梦想尤为重要,所以此文章送给有缘人,为祖国的各行各业完成赋能的使命。

前两篇文章

低代码信创开发核心技术(一):基于Vue.js的描述依赖渲染DDR实现模型驱动的组件
低代码信创开发核心技术(二):手撕灵活好用的Vue拖拉拽布局系统

数据库层设计

自顶向下出发来判定设计,我们已经有了界面和组件,接下来就是需要通过组件来访问元数据层,元数据层再调用数据库层完成与数据库的交互。

1、从API角度入手

实现链式增删改查API编程,关键点是在每一次函数执行后返回当前的对象,而不是返回结果。争取让程序员使用的时候只需一个.就能通过IDE提示出来。大大降低二次开发的难度。
链式编程的封装,是指将API设计成一个Builder,直到最后query或update时才会产生结果,这样程序员的记忆负担最少,所有的功能都是一路“点”出来的。

2、SQL的产生

一个平台需要能支持多种数据源,所以需要建立方言机制,简单的做法是写定一个IDialect接口,用工厂模式根据不同传入的JDBC Driver类名判断使用哪个方言。
有了自动化的方言工具,我们就可以实时生成SQL了,其实说来也比较简单,常用SQL的生成无非是Where子句、OrderBy子句、LeftJoin的组合,用于检索、排序、带出关联表名称等等。
尽管可以实时生成SQL,但也会有非常复杂的SQL等待我们去手写,所以API仍要留有query和update相关方法,而且为了安全性也要强制让传递进来的参数进行预编译处理。
增删改其实非常容易实现,但查询是最难的,为了解决复杂度,则需要构建一个查询上下文,因此我们在各个环节传递这个上下文对象并补充它的各种条件,即可无视顺序、无视复杂度、无视前置各种函数的调用关系,在最终进行查询的环节才按顺序逻辑构建SQL,这样最为简单,调整起来也只需修改查询上下文的类即可,所以为了方便,建议把增删改的相关条件也融入到上下文中,还有分页条件等等,需要抽象的东西并不多,但这样做可以做到统一。

3、SQL的执行

SQL被创造出来之后,即可进入执行环节,需要注意的是如果插入的数据较多,则需要用values后面跟多个数据的语法来实现批量插入、update则需要用case when语句来实现批量更新。这样可以大大节约执行的时间。
而且SQL执行层应当直接作用于JDBC之上,因为我们假定项目里并没有Hibernate、JPA、MyBatis,纯手动造一个轮子。这样带来的好处是我们可以灵活的控制分布式事务、设置保存点、增加切面,而无需受制于其他框架的规则。

4、关于数据格式

查询的结果集一定是先转换成List<Map<String,Object>>格式,但是该类型的结果作为返回值无法进行方便的后续运算,所以需要在它基础上封装一层查询结果对象,包括我们可以把它转换成ValueObject的List(实际上低代码或无代码平台基本不需要用户自己定义ValueObject)、直接拿到唯一数据、抽取所有Map里同一个属性形成新的List,或者为了构建缓存、加速运算从而抽取出主键和Map之间对应的关系等算法。
同理,增删改操作也是操作同样的数据结构。

5、插件

我们可以定义一个统一的事件处理接口和事件处理对象,事件处理对象包含事件名称、查询上下文、是否打断执行即可。然后建立一个全局事件处理器,把事件处理的实现类可以动态注册或移除。这样我们就可以做到包括给数据自动创建主键、自动填写审计信息(创建人、创建时间、修改人、修改时间)等功能。

6、查询条件容错机制

一个好的系统一定是会允许容错的,比如我们传入的列名是驼峰式,它可以自动转换成小写字母加下划线。所以写一个过滤器,当查询上下文真正要执行前,对所传入的条件进行自动的修整。

7、数据库元数据

数据库元数据可以通过Connection对象获取,包括了有哪些表、每个表有哪些字段、什么类型的、是否是主键等信息,一旦获取到了,我们可以把它用Caffeine之类的框架放到内存中缓存起来,这样便可以动态获知是否是主键。

8、事务处理

最终事务处理我们要写一个单独的项目和Spring进行结合,比较方便的做法是定义一个Bean,返回PlatformTransactionManager类型,而我们的实现类则继承AbstractPlatformTransactionManager即可。
还需要注意,把LocalDateTime、BigDecimal等格式的前后端转换问题一并解决了,同样也是定义一个Bean,返回Jackson2ObjectMapperBuilderCustomizer对象即可。

9、动态物理表的修改

我们通过第7条已经创建了数据库的元数据,但它的setter一定是protected的,不允许其他包的类对其进行任何的修改,所以我们要创建一个副本类,可以允许修改的那种。然后写一个数据表管理器,当我们对这个副本类的实例进行修改后,把整个定义传送给数据表管理器,应当能实现自动创建表、增加字段、增加索引的功能,同样的这些SQL也应当由方言插件负责完成拼装。

至此我们数据库层就完成了建设。

元数据层

我们常常在应用系统中要让系统能对自己的结构进行认知,并且要把表与表之间的外键关系、主子关系放到一个地方,在需要使用的时候从这个地方拿出关系既可自动完成一些操作,这个地方就叫做元数据层,非常类似于Java的反射机制,如果你了解了Java的反射,那么元数据层的作用就不言而喻。说到底,元数据是一种数据驱动的架构设计,实际使用时可以用一些通用的算法来处理不同的数据结构。当我们有了数据库层,就可以建立元数据层了。

1、结构定义

实体或者聚合实体只需要自身带编码、数据、子实体集合列表即可,那么我们在数据库中建立的元数据表应当也是id、code、name、pid、物理表名的格式,它是一种树状结构。随之还需要建立元数据字段表,id,code,name,物理字段名
聚合实体我们可以想象成是一个实体下面还挂有若干种实体的样子。比如入职申请表,个人基本信息完全可以放在主实体表中,而学习经历、工作经历因为和主表是1对多关系,所以学习经历、工作经历单独各是一张表,他们与主表“入职申请表”的关系就应当记录在元数据表中,当查询的时候把数据放入子实体集合列表里。
也因此,子实体集合列表实际上只需携带编码、List<数据>、分页信息即可。说是子实体集合列表,但实际上多个主实体也可以打包在一个子实体集合列表对象中。这样我们就可以形成一个无限嵌套的数据结构,做出超级复杂的业务数据结构,保障了主表和子表之间的数据一致性。
我们在实际操作元数据的时候永远操作的都是编码,读取的时候是多表按顺序自动读取并拼装,写入的时候也是视作整体。

2、执行层和事件动作

因为元数据层需要事件驱动,所以我们可以把事件简单的划分为保存、删除、查询。事件驱动实现原理非常简单,本文不做赘述。讲一下执行层究竟要做哪些事情。第一,要把数据库层的API抽离处理,比如做个QueryBuilder之类的,它可以完成对主实体(主表)的各种复杂查询。第二,需要通过数据库层的插件机制来完成主键生成、查询融入(因为数据库层有上下文,所以很容易剥离上下文并融入数据权限功能,比如未来按组织权限划分能看到的数据,实现组织 IN (组织主键清单)这类操作)。
另外在执行更新的时候还需特意注意审计信息中的最后修改时间是否有动过,为了保证多人同时修改时数据一致性,则需要将之前的数据读入,并对比时间戳,确保可以修改并给予新的时间戳,否则就应当提示用户数据已被他人修改。带入旧数据也会带来一些好处,比如我们可以在前端对子实体进行删除时,我们可以准确的得知哪些数据被删除了,从而执行删除校验,避免关键数据被删除。

3、关联定义

如果只有基本的结构定义,没有关联定义,这个系统就只能做简单的增删改查了。关联定义我们可以遵循2NF范式,将表与表之间的一对多关系存储在数据表里,到使用的时候(比如订单明细的商品ID自动翻译成商品名称)就非常有用了。
因此在查询完成后在事件驱动的查询After切面到达时,我们可以遍历主实体的树形结构,把关联到其他表的主键或者编码暂存到一起,然后批量发起查询,以字段名$name字段名$code为键保存到返回的聚合实体中。

4、实体服务和控制器基类的封装

我们有了以上内容即可完成Service和Controller的封装,善于运用@PathVariable和@RequestBody可以让你事半功倍。需要注意的是我们这里要且仅要一个主入口,后续要根据操作来分发到不同的处理类上进行处理,这样我们可以将平台框架封装起来并用spring.factories机制来实现自动注入,这样在程序员眼里看来项目就一点都不复杂了,依赖你的项目就可以获得全部元数据能力。

5、联动结构

接下来需要有一个联动结构,从前台传递元数据的定义,然后联动把元数据表、元数据字段表的内容填充进去。然后再根据元数据的定义和表和表之间关联的结构,把数据表建立起来,这就需要调用数据库层的物理表修改功能了。

初步实现低代码开发

接下来我们根据前两篇文章讲述前端的技术基础,把项目面板、属性面板搭建出来,然后在属性面板里我们可以做一个弹窗,针对某一个组件创建元数据或选择已有的元数据,弹窗界面里一开始有一个输入框,询问这里需要有哪些字段(只需要给中文名),然后预先写好prompt调用AI,把字段英文名、类型返回回来让用户确认,如果用户觉得不对,可以修改成想要的,点击保存即可自动联动创建表(如果表中没有数据,想删也是可以删的),这种程度的业务逻辑相比于非常抽象的元数据还是非常容易实现的。
后续使用已经有的元数据就没这么麻烦了,连输入框都不需要,只需要把已经有的元数据选中,勾选要展示的字段,点确定即可
最后运行时环境把设计器代码隐藏掉,只需要渲染即可。至此低代码平台的雏形就有了。

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

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

相关文章

光刻掩膜版怎么制作的?

光掩膜版基本上是 IC 设计的“主模板”。掩模版有不同的尺寸。常见尺寸为 6 x 6 英寸一般的掩膜版由石英或玻璃基板组成。光掩膜版涂有不透明薄膜。更复杂的掩模版使用其他材料。 一般来说&#xff0c;术语“photo mask”用于描述与 1X 步进机或光刻系统一起使用的“主模板”。…

Ubuntu 安装常见问题

1. 安装oh my zsh 搜狗输入法不能用 vim /etc/environmentexport XIM_PROGRAMfcitx export XIMfcitx export GTK_IM_MODULEfcitx export QT_IM_MODULEfcitx export XMODIFIERS“imfcitx” export LANG“zh_CN.UTF-8”配置完后重启&#xff0c;稍等一会&#xff0c;右上角会有个…

Windows下Python及Anaconda的安装与设置之保姆指南

学习Python编程需要安装基本的开发环境。 &#xff08;1&#xff09;python ——编译器&#xff1b;这个是任何语言都需要的&#xff1b;必需&#xff01; &#xff08;2&#xff09;Anaconda ——主要的辅助工具&#xff0c;号称是 Python‘OS&#xff1b;必需&#xff01; …

python机器学习——随机森林

随机森林 随机森林&#xff08;Random Forest&#xff09;是一种集成学习方法&#xff0c;它通过构建多个决策树并结合它们的预测结果来进行分类或回归。 算法原理&#xff1a; 决策树&#xff08;Decision Tree&#xff09;: 随机森林由多个决策树组成。决策树是一种基于树…

如何在PPT中去除编辑密码?

&#xff1a;忘记PPT幻灯片密码&#xff1f;最简单的办法在这里&#xff01; 【摘要】&#xff1a;具体步骤如下&#xff1a;第一步百度搜索【密码帝官网】&#xff0c;第二步点击“立即开始”&#xff0c;在用户中心上传文件即可。不用下载软件&#xff0c;手机电脑都可以用。…

Pytorch实战教程(一)-神经网络与模型训练

0. 前言 人工神经网络 (Artificial Neural Network, ANN) 是一种监督学习算法,其灵感来自人类大脑的运作方式。类似于人脑中神经元连接和激活的方式,神经网络接受输入,通过某些函数在网络中进行传递,导致某些后续神经元被激活,从而产生输出。函数越复杂,网络对于输入的数…

云架构师学习------腾讯云通识-存储与数据库

云架构师学习------腾讯云通识-存储与数据库 云架构师学习------腾讯云通识-存储与数据库存储基础存储服务对象存储-COS产品概述功能概览产品优势 云硬盘-CBS产品概述产品功能产品优势云硬盘类型 文件存储-CFS产品概述产品功能产品优势文件存储类型及性能规格存储类型性能与规格…

图论09-桥和割点

文章目录 1 寻找桥的算法2 桥的代码实现3 寻找割点的算法4 割点的代码实现 1 寻找桥的算法 2 桥的代码实现 package Chapt06_Bridge;import java.util.ArrayList;public class FindBridges {private Graph G;private boolean[] visited;//ord数组记录访问的顺序private int or…

51单片机PCF8591数字电压表数码管显示设计( proteus仿真+程序+设计报告+讲解视频)

PCF8591数字电压表数码管显示 1.主要功能&#xff1a;讲解视频&#xff1a;2.仿真3. 程序代码4. 设计报告5. 设计资料内容清单&&下载链接资料下载链接&#xff08;可点击&#xff09;&#xff1a; 51单片机PCF8591数字电压表数码管设计( proteus仿真程序设计报告讲解视…

计蒜客详解合集(2)期

目录 T1126——单词倒排 T1617——地瓜烧 T1612——蒜头君的数字游戏 T1488——旋转单词 T1461——校验信用卡号码 T1437——最大值和次大值 T1126——单词倒排 超级水的一道题&#xff0c;和T1122类似但更简单&#xff0c;分割后逆序输出即可~ 编写程序&#xff0c;读入…

Linux系統下查看处理器信息

在 Linux 系统中&#xff0c;可以使用 lscpu 命令来查看处理器的信息。该命令会显示有关 CPU 架构、核心数、线程数、缓存等级和大小等详细信息。 要使用 lscpu 命令&#xff0c;只需在终端中输入以下命令并按下回车键&#xff1a; lscpu执行后&#xff0c;将显示处理器的相关…

2023最新版本 从零基础入门C++与QT(学习笔记) -2- 命名空间的使用

&#x1f38f;在不同的命名空间变量名可相同 创建(如下方代码块) &#x1f384;分析一下构成 &#x1f388;-1- namespace 关键字命名空间 &#x1f388;-2- wm9 空间名称 &#x1f388;-3-括号里边正常定义变量即可 namespace wm9 {int a 99;char b A;float c 9.99;char…

Harbor(V2.8+) 登录时报错 net/http: TLS handshake timeout

问题描述 最近将harbor从v1.8 升级到v2.8后&#xff0c;客户端在登录时出现了以下问题&#xff1a; net/http: TLS handshake timeout解决方案 由于V2.8版本的nginx代理中只有配置TLSv1.2协议&#xff0c;没有TLSv1.1协议的支持&#xff0c;导致了部分客户端无法的登录。 在…

Django——orm模块创建表关系

django orm中如何创建表关系 1. 表关系分析 表与表之间的关系: 一对多 多对多 一对一 没有关系 判断表关系的方法: 换位思考用4张表举例: 图书表 出版社表 作者表 作者详情表图书和出版社是一对多的关系 外键字段建在多的那一方图书和作者是多对多的关系 需要创建第三张表来…

振南技术干货集:研发版本乱到“妈不认”? Git!(1)

注解目录 1、关于 Git 1.1Git 今生 (Git 和 Linux 的生父都是 Linus&#xff0c;振南给你讲讲当初关于 Git 的爱恨情愁&#xff0c;其背后其实是开源与闭源两左阵营的明争暗斗。) 1.2Git的爆发 (Git 超越时代的分布式思想。振南再给你讲讲旧金山三个年轻人创办 GitHub&…

Java设计模式之访问者模式

目录 定义 结构 案例 优点 缺点 使用场景 扩展 分派 案例实现须知 动态分派 静态分派 双分派 定义 封装一些作用于某种数据结构中的各元素的操作&#xff0c;它可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作。 结构 访问者模式包含以下主要角色…

普华永道于进博会首发“企业数据资源会计处理一体化平台”

11月6日&#xff0c;在第六届中国国际进口博览会上&#xff0c;普华永道发布企业数据资源会计处理一体化平台&#xff08;英文名为Data Accounting Platform&#xff0c;简称DAP&#xff09;。该产品以普华永道“五步法”数据资源入表路径为理论依据&#xff0c;依托多年来普华…

C语言编写函数将字符串逆序存放

文章目录 1-12题例题13例题13答案答案一答案二 1-12题 C语言基础例题1-3题-指针篇 C语言基础例题4-5题-二维数组篇 C语言基础例题6-7题-结构体篇 C语言基础例题8-9题-大作业篇 C语言基础例题10-11题-字符串、指针篇 C语言基础例题12题-链表篇 例题13 请编写一个函数 void re…

现在个人想上架微信小游戏已经这么难了吗...

点击上方亿元程序员关注和★星标 引言 大家好&#xff0c;最近我突然想起来我还有一款微信小游戏还没有上架&#xff0c;于是捣鼓了一天把游戏完善了一下&#xff0c;然后准备提交审核&#xff0c;却发现异常的艰难… 1.为什么难&#xff1f; 相信大家都大概知道&#xff0c…

分布式id生成数据库号段算法的golang实现

分布式id生成数据库号段算法的golang实现 介绍项目结构使用说明核心流程说明1. 定义id生成器结构体2. id生成器共有Monitor&#xff0c;GetOne, Close三个对外暴露的方法。3. 数据表结构 参与贡献 介绍 项目地址&#xff1a;gitee&#xff1b;github 本项目主要利用go语言(go1…