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

本文主要是介绍低代码信创开发核心技术(三):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,把字段英文名、类型返回回来让用户确认,如果用户觉得不对,可以修改成想要的,点击保存即可自动联动创建表(如果表中没有数据,想删也是可以删的),这种程度的业务逻辑相比于非常抽象的元数据还是非常容易实现的。
后续使用已经有的元数据就没这么麻烦了,连输入框都不需要,只需要把已经有的元数据选中,勾选要展示的字段,点确定即可
最后运行时环境把设计器代码隐藏掉,只需要渲染即可。至此低代码平台的雏形就有了。

这篇关于低代码信创开发核心技术(三):MDA模型驱动架构及元数据系统设计的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/390625

相关文章

基于 Cursor 开发 Spring Boot 项目详细攻略

《基于Cursor开发SpringBoot项目详细攻略》Cursor是集成GPT4、Claude3.5等LLM的VSCode类AI编程工具,支持SpringBoot项目开发全流程,涵盖环境配... 目录cursor是什么?基于 Cursor 开发 Spring Boot 项目完整指南1. 环境准备2. 创建

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

Redis实现高效内存管理的示例代码

《Redis实现高效内存管理的示例代码》Redis内存管理是其核心功能之一,为了高效地利用内存,Redis采用了多种技术和策略,如优化的数据结构、内存分配策略、内存回收、数据压缩等,下面就来详细的介绍... 目录1. 内存分配策略jemalloc 的使用2. 数据压缩和编码ziplist示例代码3. 优化的

Python 基于http.server模块实现简单http服务的代码举例

《Python基于http.server模块实现简单http服务的代码举例》Pythonhttp.server模块通过继承BaseHTTPRequestHandler处理HTTP请求,使用Threa... 目录测试环境代码实现相关介绍模块简介类及相关函数简介参考链接测试环境win11专业版python

Python从Word文档中提取图片并生成PPT的操作代码

《Python从Word文档中提取图片并生成PPT的操作代码》在日常办公场景中,我们经常需要从Word文档中提取图片,并将这些图片整理到PowerPoint幻灯片中,手动完成这一任务既耗时又容易出错,... 目录引言背景与需求解决方案概述代码解析代码核心逻辑说明总结引言在日常办公场景中,我们经常需要从 W

Python实战之SEO优化自动化工具开发指南

《Python实战之SEO优化自动化工具开发指南》在数字化营销时代,搜索引擎优化(SEO)已成为网站获取流量的重要手段,本文将带您使用Python开发一套完整的SEO自动化工具,需要的可以了解下... 目录前言项目概述技术栈选择核心模块实现1. 关键词研究模块2. 网站技术seo检测模块3. 内容优化分析模