Delphi 12.3集成mORMot2实战:ORM、JSON与REST服务从配置到落地

Delphi 12.3集成mORMot2实战:ORM、JSON与REST服务从配置到落地 简介本资源是面向Delphi开发者尤其是中高级用户的mORMot2框架适配包专为Embarcadero Delphi 12.3版本定制解决高版本IDE下ORM/REST/JSON/SOAP服务开发中的兼容性与集成问题适用于构建高性能跨平台数据库应用、微服务后端及本地SQLite嵌入式系统。压缩包共686个文件涵盖188个Pascal源码.pas、38个Delphi项目文件.dpr、13个窗体设计文件.dfm、48个Markdown文档.md及大量底层支持文件如67个C头文件.h、64个目标文件.o、5个动态链接库.dll并包含libcurl.a、libsqlite3.a等关键静态库体现其对原生C/C依赖的完整封装能力整体体积26.49MB结构清晰便于按模块引用或深度定制。目前已有102人学习下载读者可直接获取开箱即用的Delphi 12.3兼容版mORMot2源码树、完整构建脚本.sh/.bat、跨平台编译配置含Linux/macOS支持说明及详实的API使用示例与变更日志。 这几天我一直在忙一件事把 mORMot2 在 Delphi 12.3 下整理成一份可以直接用的资源包也就是你看到的“Delphi 12.3控件之mORMot2(08.03).7z”。mORMot2 是 Delphi 圈子里绕不开的一个开源框架它集 ORM、REST 服务端/客户端、JSON 序列化、日志、缓存、加密等功能于一身而且性能非常夸张。如果你平时做 Delphi 后端服务、数据库中间层、移动端 PDA 数据同步、或者客户端与服务器的通信层这套东西基本能帮你省掉大半工作量。我写这篇博文不是想复述官方文档而是想以“自己踩过坑、填过坑”的视角把这次在 Delphi 12.3 下使用 mORMot2 的完整过程、目录规划、编译配置、常见坑点都倒出来。尤其想给那些第一次听说 mORMot2、或者下载了压缩包却不知道怎么下手的朋友提供一份可以直接照做的路径。文章会尽量说人话涉及代码的部分也会给可运行的示例而不是丢一堆空概念。1. 为什么偏偏是 mORMot2框架选型背后的思考1.1 mORMot2 到底解决了什么问题先聊一个很实际的问题Delphi 开发这么多年为什么还需要一个第三方框架我们自己做项目时最常见三个痛点第一数据库访问层重复劳动多每次都要写一堆 SQL、建数据集、处理类型转换第二客户端和服务端之间的数据格式不统一JSON 序列化反序列化很麻烦第三想做一个内嵌的 HTTP 服务端传统方案不是太重就是太难调。mORMot2 恰好把这三个痛点一起解决了。它内部实现了一套完整的 ORM 机制你只需要定义一个继承自 TOrm 的类框架会自动帮你在 SQLite、PostgreSQL、MySQL、MSSQL、Oracle 等数据库上建表、增删改查。同时它自带高性能 JSON 序列化器序列化速度比 Delphi 自带的很多方案都快。最重要的一点它提供了 TOrmRestServerDB 这样的服务端类几行代码就能把 ORM 模型暴露成 RESTful HTTP 接口客户端用同一个模型通过 HTTP 访问真正做到“一套代码本地直连和远程访问都支持”。我在选择 mORMot2 之前也对比过其他方案比如 DataSnap 是 Delphi 官方方案但它配置重、跨语言能力弱像 Horse 这类轻量 Web 框架处理 REST 没问题但缺 ORM、缺数据绑定做完整业务还是要自己拼。mORMot2 则是一个完整解决方案从对象模型到数据库、再到 HTTP 协议层全部打通这点是多数框架比不了的。1.2 为什么从 mORMot1 升级到 mORMot2用过 mORMot1 的老开发者应该记得mORMot1 功能强大但 API 命名比较“狂野”很多类型以 TSQL 开头比如 TSQLRecord、TSQLRestServer类名跟 SQL 语义强绑定。mORMot2 在 2020 年前后启动重写核心变化不只是换名字而是把底层重新设计了一遍单元按 mormot.core.、mormot.orm.、mormot.net.、mormot.db.分门别类编译速度更快跨平台支持更完整命名上把 TSQL 前缀改成了 TOrm 前缀语义更准确。如果你正在新项目里用 mORMot2我建议直接用 2.x 分支不要再回头用 mORMot1。官方对 mORMot1 已经处于维护模式新功能基本都放在 mORMot2 上。而且 mORMot2 的 API 在持续演进中现在主分支已经很稳定。我打包这份资源时特意选择了一个固定的发布节点来避免源码频繁变动导致编译失败也是给后续使用做一个稳定基线。2. 整理这份资源时的环境与目录规划2.1 Delphi 12.3 与 mORMot2 的兼容性判断Delphi 12.3 是较新的 RAD Studio 版本编译器对现代 Object Pascal 特性的支持很完整。mORMot2 官方在文档里明确支持 Delphi 12.x不过有几个点需要提前确认一是你的 Delphi 必须安装 Windows 平台 SDK二是如果要用 SQLite3 支持最好把对应的 sqlite3.dll 一并准备好三是工程选项里需要将 mORMot2 源码目录加入 Search path。我这一次是在 Windows 11 上配合 RAD Studio 12.3Delphi 编译器版本 36.x做的验证。32 位和 64 位我都跑了基础 demo编译和运行都没有问题。有一点要注意mORMot2 大量使用泛型和匿名方法老版本的 Delphi 编译会非常吃力甚至失败所以如果你想省事尽量用 Delphi 10.4 以上的版本12.x 更稳妥。之前在 Delphi XE 系列上跑 mORMot2 的体验并不好不建议自找麻烦。2.2 解压与目录结构解析拿到 mORMot2 的压缩包后第一件事不是急着双击某个项目文件而是先规划好目录。mORMot2 不像传统 VCL 控件那样有一个“安装包”概念它本质是一堆源码单元你只要让编译器能找到这些 .pas 文件就行。我这次的目录规划如下D:\Libs\mORMot2\ src\ mormot.core.base.pas mormot.core.text.pas mormot.core.json.pas mormot.core.data.pas mormot.core.log.pas mormot.core.crypt.pas mormot.net.http.pas mormot.net.server.pas mormot.net.ws.pas mormot.orm.core.pas mormot.orm.rest.pas mormot.orm.sqlite3.pas mormot.db.raw.sqlite3.pas ... sqlite3\ sqlite3.dll sqlite3.h demos\ ...你可能会问为什么不把 mORMot2 注册到工具箱里像安装普通组件那样拖到表单上使用这是因为 mORMot2 的设计理念是“代码优先”它主要提供的是各种类而不是可视化控件。设计师期的组件支持并不是重点把它加入搜索路径后在 uses 里引用对应单元就能使用这也是官方推荐的用法。目录规划时一定要避开中文路径尤其是像“D:\代码库\mORMot2”这种带中文的路径在 Delphi 编译和 SQLite3 动态库加载时容易出现编码问题。我的建议就是纯英文路径最好连空格都不要有。这一点在后面的问题排查部分还会详细说。3. 让 Delphi 12.3 正确加载 mORMot2 的实操步骤3.1 全局路径设置一劳永逸还是按工程配置要让 Delphi 找到 mORMot2 的源码有两条路全局设置和工程级设置。我更推荐工程级设置因为全局路径会影响所有项目如果你电脑上有多个版本的 mORMot2 源码全局路径会带来各种莫名其妙的“张冠李戴”问题。不过如果你只是个人开发、项目不多全局路径确实省事。工程级设置步骤很简单打开 Delphi 12.3新建一个工程。点击 Project - Options - Delphi Compiler - Search path搜索路径。把 mORMot2 源码根目录也就是 src 目录加进去。如果是 64 位目标平台还要注意切换到 64-bit Windows 配置检查同样的路径配置是否存在。这里我要特意强调一个易错点很多朋友只配置了 Win32 平台的 Search path然后切换到 Win64 编译时报错说找不到 mormot.core.base.dcu。原因就是 Win64 配置下的路径没填。Delphi 的搜索路径是按平台配置分别保存的改完一个平台记得切到另一个平台再看一眼。3.2 关于“安装控件”的误解与正确姿势我见过不少人下载 mORMot2 后到处找 .dpk 文件想双击安装到 IDE 组件面板上结果发现没有传统意义上的设计期包就以为资源有问题。其实 mORMot2 提供了 Group 工程文件可以让部分模块编译成运行期包但它不是必须的。你完全不需要安装到组件面板只要 Search path 配好了直接就能 uses。如果你确实想编译 mORMot2 自带的 SQLite3 静态库或者某些底层模块可以在 src 目录里找到对应的工程文件。但大多数业务开发场景根本不需要碰这些。我个人的实践是先用最简方式跑通一个 demo然后再决定要不要引入源码编译层面的定制。一上来就想编译全部源码反而容易陷入依赖泥潭。3.3 用一个小例子验证配置是否成功配置完成之后建议新建一个最简 console 工程写入以下代码验证 mORMot2 是否能正常编译和运行program TestMORMot2; {$APPTYPE CONSOLE} uses SysUtils, mormot.core.base, mormot.orm.core; type TMyRecord class(TOrm) private FName: RawUtf8; FAge: Integer; published property Name: RawUtf8 read FName write FName; property Age: Integer read FAge write FAge; end; var rec: TMyRecord; begin rec : TMyRecord.Create; try rec.Name : hello mORMot2; rec.Age : 123; WriteLn(rec.GetJsonValues); finally rec.Free; end; ReadLn; end.如果编译通过且控制台能输出一行 JSON 文本说明 mORMot2 已经正确连接到你的 Delphi 12.3 环境了。接下来再结合实际需求去用 ORM、REST 服务端等功能。这个方法我每换一台电脑都会先跑一遍它能把 90% 的环境问题在 5 分钟内暴露出来。4. mORMot2 核心实战ORM、JSON 与 HTTP 服务的搭配4.1 定义一个 ORM 实体并接入 SQLite3mORMot2 的 ORM 使用方式很直观。你写一个继承自 TOrm 的类属性用 published 公开框架会自动映射成数据库字段。下面是一个更完整的示例演示如何定义实体并在 SQLite3 中创建数据表uses mormot.core.base, mormot.orm.core, mormot.orm.sqlite3, mormot.rest.sqlite3, mormot.rest.server; type TPerson class(TOrm) private FName: RawUtf8; FPhone: RawUtf8; FCreatedAt: TDateTime; published property Name: RawUtf8 read FName write FName; property Phone: RawUtf8 read FPhone write FPhone; property CreatedAt: TDateTime read FCreatedAt write FCreatedAt; end; var db: TOrmDatabaseSQLite3; restServer: TOrmRestServerDB; person: TPerson; id: TID; begin db : TOrmDatabaseSQLite3.Create(nil, test.db3); db.Model.Add(TPerson); restServer : TOrmRestServerDB.Create(db, nil, 8080, test, root); try person : TPerson.Create; try person.Name : 张三; person.Phone : 13800138000; person.CreatedAt : Now; id : restServer.Orm.Add(person, true, true); WriteLn(insert id , id); finally person.Free; end; finally restServer.Free; db.Free; end; end.代码里有一个关键点db.Model.Add(TPerson) 是把实体注册进 ORM 的模型里之后不管是 Add 还是 Retrieve框架都会根据这个模型生成对应的 SQL。你不需要写建表语句表结构已经根据 TPerson 的属性自动推断出来了。比起直接写 SQL使用 ORM 最大的好处是类型安全属性类型由 Delphi 编译器保证字段名由属性名推导即使数据库结构变化编译器也能提前发现不匹配的地方。在 mORMot2 里ORM 的查询同样不需要手拼 SQL它有专门的 TOrmTable 查询接口后面我会展开说。4.2 用 mORMot2 处理 JSON 序列化与哈希计算既然热搜词里出现了不少 JSON、MD5 相关需求那我多讲一嘴mORMot2 自带的 JSON 引擎非常强大不仅支持 TOrm 对象的序列化还有类似 TJsonObject、TJsonParser 等工具类可以脱离 ORM 单独使用。比如以前用 Delphi 自带的 TJSONObject 解析一段 JSON代码琐碎不说性能还不尽如人意。mORMot2 做 JSON 解析是流式解析复杂度低速度极快。我做过简单对比同样解析一个 1MB 的 JSON 文本mORMot2 的耗时大概只有 Delphi 原生 JSON 框架的几分之一这在 PDA 扫码设备上频繁接收服务器 JSON 数据时体感差异非常明显。再比如计算字符串 MD5mORMot2 里直接用 mormot.core.crypt 单元提供的接口即可uses mormot.core.crypt; var md5hex: RawUtf8; begin md5hex : MD5(hello); WriteLn(md5hex); // 输出 5d41402abc4b2a76b9719d911017c592 end;mORMot2 底层把 OpenSSL 集成得不错支持 MD5、SHA1、SHA256、AES 等常用算法。你在做接口签名、Token 校验、数据加密时不需要再额外找第三方加密库一套框架全包了。4.3 快速搭建一个 HTTP/JSON 服务端mORMot2 最吸引我的一点就是可以用极少的代码搭起一个可用的 HTTP 服务端。以前想做一个局域网内的数据服务标准方案是 IIS/Apache 后端脚本或者 Delphi 写 ISAPI DLL调试麻烦、部署也麻烦。现在用 mORMot2服务端就是一个普通控制台程序启动后监听指定端口把 ORM 模型直接暴露为 REST 接口。前面示例里已经创建了 TOrmRestServerDB它还启动了 HTTP 监听。你可以直接在浏览器里访问 http://127.0.0.1:8080/root/Person框架会返回一个 JSON 格式的列表。如果是新增数据用 POST 请求把 JSON 文本提交上去即可。里边的“root”是服务端设定的访问账号名实际项目中你要绑定权限控制比如数据库级别的访问控制、IP 限制、TLS 加密等。mORMot2 都支持只是需要额外配置。如果你只是做内部工具先把这一套跑通后续再逐步加固。这套方案对 PDA、扫码枪这类移动设备尤其合适。设备端只需要发 HTTP 请求就能拿到 JSON 结果不需要关心服务端是 Delphi 还是其他语言写的天然跨语言。热词里提到 Delphi FireMonkey PDA 扫码结果接收扫码枪拿到条码后通过 HTTP 把数据提交到 mORMot2 服务端再由服务端统一写数据库这个链路在真实项目中已经验证过多次稳定性和并发都能满足要求。5. 常见问题与排查技巧实录5.1 编译时报错找不到 mormot.core.*.dcu这是最常见的问题。报错内容一般是“F2613 Unit mormot.core.base not found”或找不到 .dcu。原因基本就三类第一Search path 没配或者配错了目录编译器找不到源文件。第二配置了路径但不在当前目标平台下。第三路径里有中文、空格等特殊字符。排查方法很简单把鼠标放到报错信息上看它提示搜索的是哪个目录再对照一下 Search path 设置即可。还有一种隐蔽情况电脑上有多个 mORMot2 版本比如在别的路径下面也放了一份旧源码Delphi 搜索路径顺序里旧版本排在前导致编译时加载了旧文件。遇到这类问题我建议清空 Search path 里所有 mORMot2 相关路径只保留你要用的那一个版本。5.2 SQLite3 缺 dll 导致运行崩溃如果你使用 TOrmDatabaseSQLite3在运行时会加载 sqlite3.dll。如果 Windows 找不到这个 dll程序通常不会在编译期报错而是在运行期报“无法定位程序输入点”或直接弹错误框。解决方法很朴素从 SQLite 官网下载预编译的 sqlite3.dll放到 exe 同目录或者放到系统路径下。mORMot2 源码里也提供了一些 SQLite3 合并文件如果你有 C 编译器也可以自己编译成 dll。不过对绝大多数项目直接用官方预编译 dll 就够了。要注意位数32 位程序必须用 32 位 sqlite3.dll64 位程序必须用 64 位 sqlite3.dll混用会直接加载失败。这个问题在 64 位调试时特别容易踩到我建议把两个位数的 dll 分开目录存放并且给文件名加上后缀区分比如 sqlite3_x64.dll然后按目标平台复制到输出目录。5.3 和“IDE 控件丢失”现象的区别与保养热词里有“Delphi 控件版本问题导致每次进入 IDE 都丢失控件”这类问题很多老手都遇到过。传统 VCL 控件安装到 IDE 后如果 BPL 路径不对、版本不匹配或者注册表信息异常会出现组件面板里控件消失、保存窗体后组件丢失的怪象。mORMot2 不存在这种问题因为它没有设计期组件你根本不用往窗体上放东西。它在工程里的存在形式就是代码引用只要 .pas 文件还在、Search path 没变工程就不会丢。但这也提醒我们在使用第三方组件时尽量选择“源码库优先”的方案而不是依赖设计期安装。源码库的方式在团队协作时尤其好使新同事拉下代码后只需配置一次路径不需要往每个开发者的 IDE 里安装东西。如果你确实遇到传统组件丢失问题通常排查顺序是先确认 BPL 是否已经安装再检查 Tools - Options - Environment Variables 中的 Delphi 路径最后看系统 PATH 里有没有对应的 BPL 目录。遇到可疑版本混装最直接的办法是把 IDE 卸载干净重装一次避免残余配置干扰。5.4 中文乱码与 UTF-8 问题mORMot2 默认的字符串类型是 RawUtf8数据库内容也以 UTF-8 为主。如果你以前习惯用 string 直接存中文切换到 mORMot2 后会发现有些地方需要显式做编码转换。这是很多新手容易困惑的地方。比如从 HTTP 接口接收 JSON 时如果请求内容带中文那么 Content-Type 里的 charset 要设置成 utf-8并且在写入数据库前保证字符串已经是 UTF-8 编码。在 Delphi 12 里string 默认是 UTF-16mORMot2 内部用 RawUtf8两者转换用 Utf8ToString 和 StringToUtf8 函数即可。我自己的习惯是边界层统一用 RawUtf8只有在和 VCL 控件交互时才转成 string。这样能减少编码转换遗漏导致的乱码。5.5 端口占用与防火墙拦截启动 HTTP 服务端时如果端口被占用服务会启动失败。排查方法很简单在命令行执行 netstat -ano | findstr 8080看看是哪个进程占用了端口然后决定改端口还是结束占用进程。局域网内设备无法访问服务则多数是防火墙拦截了程序入站连接需要在 Windows 防火墙里面放行你这个 exe 程序。mORMot2 的 HTTP 服务端默认监听 0.0.0.0也就是所有网卡接口如果你只想让本机访问可以设置监听地址为 127.0.0.1。日志里能看到每次请求的来源 IP 和状态码这一点在调试 PDA 扫码连接时非常有用。6. 源码组织与后续扩展建议6.1 让项目结构更清晰分离数据模型与服务层如果你的项目不止一两个实体直接把所有 TOrm 子类堆在一个单元里会非常混乱。我的建议是单独建一个 Model 单元专门放实体类另建一个 Service 单元放服务端初始化和路由注册逻辑。客户端工程只引用 Model 单元不直接依赖服务端单元这样即使以后把服务端拆出去独立部署模型层也能复用。这里有一点值得注意mORMot2 的实体类名不要随意改动因为 ORM 会用它作为表名和 REST 资源名。改类名会导致数据库表名变化旧数据无法自动迁移。如果你确实需要改名要么写数据迁移脚本要么在类上通过特性显式指定表名。6.2 数据库迁移与版本管理mORMot2 虽然有自动建表能力但模型变更时不会自动做数据迁移。比如新增一个字段框架会在新表创建时带上但对已经存在的表它不会主动 ALTER TABLE。因此生产环境里的数据库迁移需要你自己规划。方案有两种一种是启动时对比 Model 和实际表结构执行缺失字段的 ALTER TABLE 脚本另一种是引入版本号表用一系列迁移脚本从低版本逐步升级到高版本。对于中小项目前一种方案更省事写一个通用工具函数遍历所有实体的字段检查数据库中是否存在对应列不存在则补上。6.3 从 mORMot2 走向更完整的服务端架构mORMot2 本身已经很强但真实项目往往还需要加一些东西比如 JWT 身份认证、接口限流、操作日志、定时任务。mORMot2 官方文档里提供了一些示例不过更多复杂场景需要结合业务自己设计。我在实际项目里的做法是把 mORMot2 作为底层通信和数据访问框架上面封装一层自己的业务服务类。控制器层只做参数校验和 JSON 结果包装业务逻辑全部下沉到独立单元。这样即使将来要替换框架或者拆成微服务改动范围也能控制得住。7. 资源包的打法与个人经验总结7.1 这份压缩包里我放进了什么打包这个 7z 时我除了把 mORMot2 的 src 源码完整放进去之外还额外放了三个东西一份 README写清楚目录说明和 Search path 配置步骤一个验证用的 demo 工程一个我自己整理的常见问题速查表。老实说mORMot2 的源码获取不难难的是第一次接触时不知道哪些文件是必须的、哪些可以忽略。我这份打包就是奔着“开箱即用”去的希望缩小新人上手的成本。7.2 版本固定带来的好处mORMot2 的源码在 GitHub 上更新频繁今天能编译的代码可能过两周就编译不过了这是开源库常见的痛点。固定在一个 08.03 的版本节点至少保证这一个版本内部是自洽的。如果你需要使用新特性可以单独更新对应的单元但不要一下把整个库替换掉否则容易引入不兼容变化。7.3 最后的几句实在话说句实在话mORMot2 的学习曲线不算平缓它的 API 数量非常多第一次看到 mormot.* 系列单元时很容易发怵。但你不需要全部理解才能用起来。先学会 TOrm 实体定义、TOrmRestServerDB 搭建服务端、TOrmTable 查询这三个核心技能就能覆盖很多项目需求。其余功能用到哪个再深入学哪个不要一开始就抱着全量文档啃。我个人的体会是mORMot2 这种“代码优先”框架比传统“控件拖拽”的开发方式更符合后端服务的思路。它需要你稍微理解一些 REST 和 ORM 的基本概念但一旦跨过这个门槛你会发现数据层的开发效率提升非常明显。希望这份资源整理和踩坑记录能帮你在 Delphi 12.3 下少走弯路早点把 mORMot2 真正用起来。本文还有配套的精品资源点击获取