拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Delphi 12.3安装mORMot2控件包:ORM与RESTful实践指南

简介本资源是面向Delphi高级开发者与跨平台服务端架构师的mORMot2框架适配包专为Delphi 12.3环境深度优化解决现代REST/JSON-RPC服务开发中ORM映射、HTTP服务器集成及SQLite/CURL底层依赖兼容性问题。压缩包共686个文件涵盖188个Pascal源码.pas、67个C头文件.h、64个目标文件.o、58个Shell脚本.sh及48份Markdown文档.md辅以DPR工程、DFM界面、LPI/LPK项目配置等完整构建要素26.49MB体量内集成了libcurl.a、libsqlite3.a、libgcc.a等关键静态库体现其对Linux/macOS交叉编译与原生动态链接的双重支持能力。已有102人下载学习可直接导入IDE构建高性能服务端应用获取含单元测试、示例服务、数据库迁移脚本及多平台部署配置在内的全栈式开发支撑体系。1. 项目背景与工具链解析1.1 为什么是 mORMot2 而不是其他 ORM看到这个标题老Delphi玩家应该马上就明白了这是给 Delphi 12.3 准备的一套 mORMot2 控件包打成了 7z 压缩包日期标注 08.03。mORMot2 对 Delphi 生态来说不只是一个 ORM 框架而是一整套底层基础设施。它涵盖了 ORM、RESTful 服务端/客户端、JSON 序列化、SQLite3 直接封装、日志系统、缓存、加解密甚至内存网格计算等一堆能力。官方喜欢叫它 Synopse mORMot 2但实际你在 GitHub 上搜到的仓库名是mormot2。我先说个结论如果你还在纠结用哪个 Delphi ORMmORMot2 是目前综合能力最强的选择之一尤其是 12.x 时代它把很多以前需要拼装多个库才能完成的事情统一到了一个代码库里。像DBX、FireDAC这种官方方案底层连的是数据库驱动而 mORMot2 更像是你自己的数据访问层——你可以直接用它连 SQLite、PostgreSQL、MSSQL也可以完全不用 SQL直接用对象映射再通过 REST 暴露给前端。相比其他开源 ORM比如tiOPF、InstantObjectsmORMot2 的性能优势在基准测试里非常明显。尤其是 JSON 序列化这块它自带的SynCommons里的 JSON 引擎比 Delphi 自带的System.JSON快了不止一个数量级。这在你做高并发 REST 接口时差距就是天壤之别。所以当你拿到这个Delphi 12.3控件之mORMot2(08.03).7z时不该只把它当成一个控件来装而应当成一套完整的应用架构底座来用。1.2 为什么单独为 Delphi 12.3 打包Delphi 12.3 是 Embarcadero 在 RAD Studio 12 系列里的一个较新版本编译器对应的是CodeGear\Delphi的 12.3 分支。mORMot2 对 Delphi 版本的支持其实很宽从老的 Delphi 6 到最新的 12.x 都能编译。但不同版本之间有几个关键点会影响 API 的可用性泛型和匿名方法老版本 Delphi 对泛型支持不完整mORMot2 里的很多高级特性比如TRecord、TJSONSchema只能在较新的编译器上跑。Delphi 12.3 对泛型、字符串内联、记录类型增强都做得很好适合把 mORMot2 的全部功能打开。跨平台编译mORMot2 在 Windows、Linux、macOS、Android、iOS 上都有对应支持。但 FireMonkey 框架在 12.3 上对 Android 的权限模型、生命周期管理有了新变化控件包的封装如果没跟上编译到 Android 时会报错。Win64 Async 网络层mORMot2 底层用的是基于 socket 的异步非阻塞模型在 Win64 下依赖synpze或libcurl。Delphi 12.3 更新了运行库的 CPU 指令集支持如果控件包不重新编译容易出现AV访问冲突或EConvertError。所以这个 08.03 的打包日期大概率是作者基于 mORMot2 官方源码针对 Delphi 12.3 的 RTL/VCL 头文件做了适配后重新 build 的产物。你在安装时不要直接拿官方 GitHub 上的最新源码乱编而应该优先用这个包里面的.dpk工程组因为它们已经验证过能在这个 IDE 版本上顺利编译。1.3 7z 压缩包里的常见内容这类控件包解压后目录结构一般是这样mORMot2 ├── src │ ├── core │ ├── net │ ├── db │ ├── rest │ ├── scripting │ ├── mvc │ └── ... ├── packages │ ├── Delphi │ │ └── 12.3 │ └── ... ├── examples ├── sqlite3 └── ...其中最重要的就是packages\Delphi\12.3下的.dpk文件。你需要打开的是类似mORMot2Package_Delphi12.groupproj这样的工程组按顺序 Build 各个运行时包再安装设计期包。有些定制版还会内置mORMot2.pas这个包含了所有核心单元的合集版本方便那些不喜欢用包管理、直接引用源码路径的人。打开压缩包之前建议你先确认一下自己的 7-Zip 版本。老版本的 7-Zip 解压这种新打包格式偶尔会出现校验错误推荐用 7-Zip 23.01 以上版本。解压到路径时也要注意不要解压到带空格或中文字符的目录比如D:\Project\mORMot2就可以D:\我的库\mORMot2 正式版这种路径很容易让后续的 IDE 库路径解析出问题。2. 安装前的准备工作2.1 确认 Delphi 12.3 的安装状态动手之前先打开 Delphi 12.3 的About对话框确认版本号确实以 12.3 开头。为什么强调这个因为 RAD Studio 12.0、12.1、12.2 和 12.3 之间System.Win.SysUtils等单元虽然向下兼容但个别函数的实现细节变了特别是涉及TFile、TDirectory这类 IO 操作时行为可能不同。如果你实际用的是 12.1 却硬装 12.3 编译出来的包大概率会在运行时出现奇怪的EInOutError。另外检查一下你有没有安装额外的第三方库比如FastMM内存管理器、madExcept异常捕获。mORMot2 的默认内存管理器在 Windows 下用的是自己的FastMM4分支如果工程里同时链接了其他内存管理器会出现重复定义GetMem的问题。我见过不止一次因为装了madExcept而跟 mORMot2 冲突的情况表现为启动时直接访问违规但栈信息完全对不上。如果你准备在 Linux 上部署那还需要确认 Delphi 12.3 的 Linux 编译环境PAServer已经配置好。mORMot2 虽然能编译到 Linux但有几个底层单元比如mormot.core.os里的/proc读取、epoll封装在 Linux 上依赖 FPC 风格的 POSIX 头文件Delphi 12.3 的 Linux 编译器对libc的某些头文件转换并不完整所以建议先在 Windows 上把包编译通过再切换到 Linux 编译。2.2 解压与目录规划解压这个 7z 包之前我强烈建议你建一个干净的目录不要直接丢到C:\Program Files或者系统盘的Users目录下。mORMot2 在编译过程中会自动生成一些.obj、.dcu文件如果放到受 UAC 保护的目录每次编译都会因为权限不足而重新编译浪费时间还容易出奇怪的问题。我自己的习惯路径是D:\Components\mORMot2\08.03解压后在 Delphi 的Tools Options Environment Variables里添加一个系统变量MORMOT2值指向解压后的根目录。这样做的好处是以后在Project Options Delphi Compiler Search Path里可以直接用$(MORMOT2)\src\core这种宏来引用换机器、换路径时不用改工程文件。这一步很多人忽略但实际维护时能省下大量精力。2.3 检查配套依赖mORMot2 的db层支持直连 SQLite3自带了一个sqlite3目录里面通常有预编译好的sqlite3.dll和对应单元文件。如果你在 64 位 Windows 上开发注意需要sqlite3_x64.dll重命名为sqlite3.dll放到执行目录中否则加载不成功。不同位数的 DLL 不能混用否则一调用TSQLite3Database就报Entry Point Not Found。如果你需要使用 mORMot2 连 PostgreSQL、MSSQL、Oracle 等数据库包内并不包含对应的客户端驱动库你需要自己准备。例如PostgreSQL需要libpq.dll且要保证 DLL 的位数与你的 EXE 一致。MSSQL走的是 OleDB 或 ODBC在 Windows 上通常系统自带但要注意 mORMot2 的 ODBC 封装在连接超时参数上与其他框架不太一样需要单独设置。Oracle需要安装 Oracle Client且设置TNS_ADMIN。这一块踩坑非常多建议先绕开用 SQLite 把功能验证完再切到企业级数据库。如果你还要用 mORMot2 的 HTTP 客户端mormot.net.http去请求外部的 HTTPS 接口那依赖的就不是数据库驱动了而是 OpenSSL。Windows 下需要libssl-3-x64.dll和libcrypto-3-x64.dll。Delphi 12.3 在 Win64 下如果没找到这两个 DLL运行时会报Socket Error # 0或者直接抛ECrtSocket。这个点很阴因为编译期完全正常只有运行到HTTP请求那一行才崩。3. 编译安装的核心环节3.1 打开工程组并选择正确平台进入packages\Delphi\12.3目录找到类似mORMot2Package_Delphi12.groupproj的文件用 Delphi 12.3 打开。如果目录下同时有_LWLibrary Wrapper版本但你只是普通应用开发不需要安装它。打开后第一件事不是直接Build而是到Project Manager里把当前平台切换到Win64。为什么要强调这个因为 Delphi 默认可能是Win32而 mORMot2 在 12.3 上针对 Win64 编译更稳妥特别是当你的项目最终要部署到 64 位 Windows Server 上时提前用 64 位编译一遍能提前发现指针截断、内存对齐之类的问题。工程组里通常包含两类包运行时包.bpl结尾名字一般叫mORMot2Core、mORMot2Net等。设计期包.bpl结尾但会注册组件到 IDE通常带Design关键字或者单独列出。编译顺序是先编译所有运行时包再编译设计期包。不要全选后一次性Build All因为包之间有依赖关系而 Delphi 的工程组依赖解析偶尔会抽风尤其在第一次编译时。按顺序右键每个包选择Build逐个来稳一点。3.2 处理编译报错常见坑与对应解法站在 12.3 的视角mORMot2 源码在新编译器上直接编译大概率会遇到下面几个典型报错。我把它们列出来免得你卡住。报错 1E2003 Undeclared identifier: RawByteString这个一般不会出现在 12.3因为你用的版本太新了。但如果你同时装了 mORMot 1.18 老版本两个版本的源码混在一起就会出现这种奇怪的符号冲突。解决办法是确保Search Path里只加 mORMot2 的目录不要加老版本 mORMot1 的。报错 2[dcc64 Error] mormot.core.os.pas(1234): E2010 Incompatible types: PChar and PWideChar这是在 Linux 或某些特殊字符集环境下才会出现的。Windows 下 Delphi 12.3 的默认字符串是UnicodeString但 mORMot2 内部大量使用RawByteString。如果你在 IDE 的项目选项里把String设为UTF-8或者改了DefaultStringCodePage就容易触发这个错。解决办法是保持默认设置不要乱改。报错 3F2588 Linker error: sqlite3.o contains invalid OMF record type这种问题多出在sqlite3目录下自带的.obj文件与你当前 CPU 位数不匹配。如果你在 Win64 下编译但库里放的是 32 位 obj就会报这个错。解决办法是把src\db\sqlite3里不必要的.obj全部排除直接改用sqlite3.dll动态加载方式也就是让mormot.db.sql.sqlite3通过LoadLibrary载入外部的 DLL。动态加载的好处是灵活避免链接期的一堆麻烦。报错 4E2010 Incompatible types: TClass and TComponentClass这个多发生在自研代码里而不是 mORMot2 本身。当你用TSQLRecord的子类时某些属性声明类型写错就会出现这种问题。建议先把错误定位到具体单元看是不是自己把某个类的类型写成了另一个不相关的类。3.3 设置 IDE 库路径编译通过并安装设计期包之后还有一个关键步骤配置全局库路径。打开Tools Options Language Delphi Library在Library Path中加入以下目录mORMot2 根目录下的src\coresrc\dbsrc\netsrc\restsrc\mvcsrc\scripting如果你用的是Runtime Packages方式也就是把 mORMot2 编成 BPL在工程里通过Require引用那可以不设Search Path因为运行时包已经在 IDE 里注册了。但如果你跟我一样喜欢把源码直接编进 EXE 里部署这样发布时不用带一堆 BPL那Search Path就必须配好。我个人的习惯是调试阶段用源码编进 EXE发布时再切换成 BPL 动态链接。为什么因为 mORMot2 的源码编译起来不算慢但每次改一句框架代码都要重新编译整个项目那体验就很不舒服了。如果你只是应用开发者不想碰框架源码那直接用 BPL 方式就最省心。3.4 验证安装是否成功装完之后怎么确认它真的能用了最快的验证方式新建一个 VCL 项目放一个按钮在点击事件里面写uses mormot.core.base, mormot.core.os, mormot.orm.core; procedure TForm1.Button1Click(Sender: TObject); begin with TSynLog.Create do try Add.Log(mORMot2 is running on %, [OSVersionText]); finally Free; end; end;如果编译通过且运行后生成了日志文件说明核心库已经没问题。接着再验证一下 ORM 基础能力定义一个继承TSQLRecord的类连上 SQLite增删改查一遍。这一步能跑通你的环境就算彻底配好了。集成到真实项目里时还有一点必须注意mORMot2 的加密证书路径、OpenSSL 配置等在不同平台上默认路径不一样。比如 Windows 下它可能去C:\Windows\System32\config\systemprofile查找证书而 Linux 下则用系统 CA 库。如果你想快速自测推荐直接用TOSProcess跑一个 HTTPS 请求看能否正常返回不能就直接检查 DLL 是否齐全。4. mORMot2 核心功能梳理与实用场景4.1 ORM 映射把数据库表变成 Delphi 类mORMot2 的 ORM 不是像 FireDAC 那样先写 SQL再把数据集映射成对象而是以类定义为中心。你定义一个类它帮你自动建表、自动生成 SQL、自动序列化 JSON。举个例子type TArticle class(TSQLRecord) private FTitle: RawUTF8; FContent: RawUTF8; FCreateTime: TDateTime; FViewCount: Integer; published property Title: RawUTF8 read FTitle write FTitle; property Content: RawUTF8 read FContent write FContent; property CreateTime: TDateTime read FCreateTime write FCreateTime; property ViewCount: Integer read FViewCount write FViewCount; end;这里有一个新手必须记住的坑mORMot2 的 ORM 属性必须是published而不是public且类型要选它能识别的类型比如RawUTF8而不是string。如果你用UnicodeString在序列化成 JSON 时会变成带 BOM 的 base64导致其他语言解析失败。我见过太多人卡在这里纠结为什么存进去是中文读出来却是乱码。定义好类之后连接数据库并执行 CRUD 就很直接了var DB: TSQLRest; Article: TArticle; begin DB : TSQLRestServerDB.Create(TArticle, test.db3, False); try Article : TArticle.Create(DB, Title?, [第一个标题]); try Article.Content : 内容...; DB.Update(Article); finally Article.Free; end; finally DB.Free; end; end;这一步走通后你会发现一个很有意思的地方你根本不需要手写INSERT INTO、UPDATE、DELETE这些 SQL 语句mORMot2 会帮你全部生成。这不仅是开发效率的提升更是代码安全性的提升——因为 mORMot2 内部对 SQL 参数做了完整的转义和预编译处理从根上规避了 SQL 注入。你只需要定义好映射类剩下的交给框架。4.2 ORM 与 SQL 查询的取舍何时该写纯 SQLmORMot2 提供了TSQLRecord的高级查询方式比如DB.Retrieve(WHERE ViewCount ? ORDER BY CreateTime DESC, [100]);这种写法很舒服但它只能满足 80% 的需求。剩下的 20%——复杂的多表 JOIN、嵌套子查询、窗口函数——你用 ORM 硬写会非常痛苦所以 mORMot2 也提供了原生 SQL 接口以及TSQLRequest直接执行 SQL 语句。比较推荐的做法是基础增删改查用 ORM复杂分析用 SQL。大部分团队也是这么玩的ORM 负责提效SQL 负责兜底。还要注意 ORM 返回的字段不一定跟你数据库表里的字段顺序一致。mORMot2 内部按published属性声明的顺序返回如果你之前用过 FireDAC 里的SELECT *那心态要调整一下——你不再依赖表的物理结构而是依赖类的逻辑结构。这在团队协作时特别有用因为改表结构只需要改一个类定义不用到处找 SQL。4.3 RESTful 服务端真正拉开差距的地方mORMot2 的 ORM 只是开胃菜真正的杀手锏是它自带的高性能 RESTful 服务端。你可以用一个类就能把 ORM 资源暴露为 HTTP 接口客户端直接通过 JSON 访问。比如type TMyServer class(TSQLRestServerDB) public procedure DoSomething(var Ctxt: THttpServerRequest); end;然后在服务创建时注册路由Server.Router.Add(GET, /api/ping, DoSomething);启动服务HTTPServer : THttpServer.Create(0.0.0.0:8080, nil, nil); HTTPServer.HttpServerRegister(Server);这样整个 CRUD 也能自动暴露成/api/root/tarticle之类的 REST 端点。配合 mORMot2 内置的TRestHttpClientDelphi 写的客户端和服务端之间通信非常顺手还能直接复用定义的 ORM 类。有一说一mORMot2 的 RESTful 性能确实非常能打。它的 HTTP 服务器是异步非阻塞模型在普通 PC 上跑出上万 QPS 毫无压力。之前我用一个普通的 Windows 服务器开了 mORMot2 的 REST 服务压测时并发 2000 个请求内存占用非常平稳响应时间几乎是一条直线。这和 Indy 那种每个连接一个线程的模型完全不是一个量级。4.4 JSON 与跨语言互操作Delphi 圈子里的数据交换以前总是头疼 JSON 的序列化和反序列化。System.JSON性能一般而且 TJSONObject 用起来非常啰嗦。mORMot2 自带了一套完整的 JSON 操作工具主要分两层底层mormot.core.json里的TJsonWriter/TJsonParser专门处理流式 JSON性能极高。高层基于RTTI的自动序列化你可以直接把一个类实例转成 JSON 字符串也能把一个 JSON 字符串变成类实例。比如var JSON: RawUTF8; Article: TArticle; begin Article : TArticle.Create; ... JSON : Article.ToJSON; // 反向 Article.FromJSON(JSON); end;配合前面说的RawUTF8类型mORMot2 生成的 JSON 是标准的 UTF-8 编码没有 UTF-8 BOM 头这对 Java、Go、Python 后端来说非常友好。我之前做过一个项目Delphi 客户端 POST JSON 给 Go 后端Go 那边直接json.Unmarshal就能解析全程没有任何编码问题。注意ToJSON默认只序列化published属性。如果你定义了public的辅助方法里面去读私有字段那这些字段不会自动出现在 JSON 里。如果你需要加密字段或者不输出的内部状态字段可以加上stored false或相关的属性说明。4.5 缓存、日志与底层工具除了 ORM 和 RESTmORMot2 还内置了非常多实用的底层工具这块在二次开发时非常香TSynLog一套高效的日志框架支持分级、分文件、压缩直接输出为 JSON 格式。它的运行速度很快Debug 环境下不会影响主流程性能。实际生产里我习惯把sllInfo级别打开把每个请求的耗时、参数、DB 操作都记下来出问题时有完整的调用链。TSynCache一个线程安全的内存缓存容器适合做热点数据缓存。内部有 LRU 淘汰策略可以直接替代自己手写的字典加锁结构。TSynTable内存中的表格结构适合做复杂的数据筛选和计算。如果你有从数据库读出数据后在内存里再做多层过滤的需求这个比TStringListTList可靠得多。TRawByteStringStream高效处理二进制数据的流类和TBytesStream比省掉了多次内存拷贝。这些工具类在日常开发中使用频率极高。特别是 TSynLog我们团队几乎所有的项目都把它作为默认日志方案因为它能无缝衔接 mORMot2 的 ORM每个数据库操作都自动打点。你要排查线上问题时直接查日志文件基本能把问题定位到具体方法和 SQL 语句。5. 实际项目集成从零搭建一个带 ORM 的 REST 服务5.1 场景设定与接口设计假设我们现在需要做一个简单的“文章发布系统”后端。需求是前端可以是 Vue、微信小程序甚至另一个 Delphi 程序通过 HTTP JSON 接口发布文章、获取文章列表、查看文章详情并且要求支持按浏览量排序。接口设计如下POST /api/article发布文章请求体为 JSON包含标题、内容、浏览量。GET /api/article获取文章列表支持?orderviewcount排序。GET /api/article/{id}获取文章详情。这个场景用 mORMot2 的 ORM REST 框架来做代码量会非常少。5.2 服务端实现打开 Delphi 12.3新建一个 VCL 项目也可以建 Console 项目但 VCL 方便调试界面然后在FormCreate里初始化服务端procedure TMainForm.FormCreate(Sender: TObject); begin // 初始化数据库 FServer : TSQLRestServerDB.Create(TArticle, article.db3, False); FServer.CreateMissingTables; // 启动 HTTP 服务 FHTTPServer : THttpServer.Create(8080, nil, nil); FHTTPServer.HttpServerRegister(FServer, true); end;这里需要注意TSQLRestServerDB.Create的第三个参数是aCreate。如果传False那么打开的数据库文件不存在时会自动创建如果传True会强制创建一个新库即使文件已经存在。如果你不想每次启动都覆盖数据一定要传False。CreateMissingTables会自动为TArticle类创建对应的数据表字段类型、长度、索引都会根据类定义自动生成。如果你的类定义中加了indexed属性这里会帮你建索引。接下来注册自定义的 REST 路由。mORMot2 允许你通过Router来注册事件FServer.Router.Add(GET, /api/health, procedure(var Ctxt: THttpServerRequest) begin Ctxt.OutContent : {status:ok}; Ctxt.OutContentType : application/json; end);如果你不想注册路由也可以用 mORMot2 默认提供的 CRUD 端点它会把 ORM 类自动映射成/api/root/tarticle。这个默认端点很不显眼但对一个快速原型来说完全够用。不过要强调一下这个默认端点名不直观前端对接时容易晕所以生产环境我还是建议用Router.Add手动定义一组对业务有意义的接口。5.3 客户端调用示例客户端我们用 Delphi 自带的TNetHTTPClient或者 mORMot2 的客户端。用 mORMot2 客户端的话可以直接复用服务端的 ORM 类型定义只需要把TArticle类放到一个公共单元里客户端和服务端都引用它。然后var Client: TSQLRestClientHttp; Article: TArticle; begin Client : TSQLRestClientHttp.Create(http://127.0.0.1:8080, TArticle); try Article : TArticle.Create; try Article.Title : 测试文章; Article.Content : 内容; Article.ViewCount : 0; Client.Add(Article, True); finally Article.Free; end; finally Client.Free; end; end;这一套下来你连 URL 拼接、JSON 手工解析都省了服务端和客户端之间直接用 Delphi 的类作为契约。说实话这种体验在当前的主流后端技术栈里很难找到类似的存在这也是为什么 mORMot2 在 Delphi 社区的地位一直很稳固。5.4 搜索与排序的坑为什么你的索引没生效很多人在 mORMot2 里做搜索时喜欢把条件直接写到WHERE里比如DB.Retrieve(WHERE Title LIKE ?, [%测试%]);这段代码能跑但如果数据量大性能会很差。因为 mORMot2 默认的 SQLite3 在这个查询里做的是全表扫描。如果你真需要全文搜索或模糊查询建议用 mORMot2 的TSQLRecord配合虚拟表FTS5或者用外部搜索服务比如 Elasticsearch。单纯在 Delphi 层面对LIKE %xxx%做优化上限很低。排序字段也一样如果你经常按ViewCount排序请在TArticle对应属性上加索引声明property ViewCount: Integer read FViewCount write FViewCount; // 在 published 前加特性声明要在类的published前面加上property ViewCount : Integer read FViewCount write FViewCount index ...这类写法来声明索引。不过 mORMot2 的索引声明更简洁你需要在类定义前加一行TSQLRecord的一个property声明。在 12.3 上更推荐的做法是创建表后手动执行CREATE INDEX这样可以精确控制索引类型和字段顺序。综合来看ORM 能帮你解决 90% 的日常操作但搜索和排序这类场景还是要回到关系和索引的本源去思考。6. 常见问题与排查技巧实录6.1 每次进入 IDE 都丢失控件需要重新放置这个热词在 Delphi 圈里出现频率很高而且跟 mORMot2 控件包也有关系。如果你装了设计期包后每次重启 IDE工具栏上的 mORMot2 组件都没了必须重新安装一遍那大概率是 IDE 的Library Path没配对或者设计期 BPL 没有正确注册到Windows 注册表的 IDE 包列表里。排查顺序打开Component Install Packages看看运行时包是否在列表里。如果在但设计期包不在说明设计期包没装上需要右键对应的.dpk文件选择Install。如果时有时无检查是不是有两个版本的 BPL 同时存在。比如之前装过 mORMot1 的设计期包再装 mORMot2 时包名冲突导致 IDE 启动加载失败。如果 IDE 报Cant load package ...先用tlist或者Process Explorer看看是不是有旧的bpl文件被占用杀掉相关进程再重装。6.2 编译期正常运行期报EDBClientError或者表不存在这个情况一般在TSQLRestServerDB.Create之后没有调用CreateMissingTables。很多老代码是从 1.18 迁移过来的老版本在某些路径下会自动建表但 2.x 版本把自动建表改成显式调用。你需要在初始化时加一行FServer.CreateMissingTables;还有另一个可能数据库文件用的是只读模式或者目标目录没有写权限。Windows 下如果放到C:\Program Files下面就会出现这种问题改成放到%LOCALAPPDATA%或者自定义目录即可。6.3TSQLRecord与TJSONObject的互相转换出现乱码大概率还是string和RawUTF8混用导致。mORMot2 内部统一使用RawUTF8但你的业务代码里可能会用UnicodeString接收外部 JSON。mORMot2 提供了一系列转码函数比如UTF8ToString、StringToUTF8你可以显式转换。另外如果你用了TJSONObject.Parse一定要指定编码类型避免系统自动识别时出现偏差var JSON : TJSONObject.Parse({title:中文});6.4 日志文件增长过快磁盘爆了TSynLog默认是无限增长你需要在初始化时设置日志保留策略。常用做法是按天切换文件保留最近 7 天TSynLog.Family.FileRotate : 1; // 每天一个文件 TSynLog.Family.FileMaxSize : 10485760; // 单个文件最大 10MB如果日志量特别大考虑把日志级别调高或者把sllDebug关闭只保留sllInfo和sllError。生产环境日志建议只记录关键操作和异常不要每条 SQL 都打否则就算有轮转也扛不住长时间高并发。6.5 连接池与多线程为什么我的服务并发一高就崩mORMot2 的 ORM 默认不是线程安全的同一个TSQLRestServerDB实例不能同时在多个线程里执行写操作。你需要使用TSQLRestServerDB自带的ThreadSafe模式或者为每个线程创建独立连接。最简单的方式FServer : TSQLRestServerDB.Create(TArticle, article.db3, False); FServer.OrmThreadSafe : True;OrmThreadSafe开启后写操作会自动排队。如果你需要更高的并发读写可以考虑读写分离多读实例 单写实例通过数据库层面的复制来同步。6.6 FireMonkey 与 mORMot2 配合时的坑如果你是用 FireMonkey 做跨平台界面比如在 Android PDA 上跑扫码程序然后用 mORMot2 做本地 SQLite 存储有几个点要提前避雷Android 上 SQLite 数据库文件路径不能随便写要用GetHomePath或TPath.Combine(TPath.GetDocumentsPath, app.db3)。直接用app.db3会写到沙箱根目录Android 10 以后基本不可写。另外FireMonkey 的TThread.Queue和 mORMot2 的回调线程配合时要注意 UI 更新必须回到主线程。mORMot2 的任何回调都不能直接在 UI 组件里操作除非你手动TThread.Queue一下。扫码场景处理时通常要让 mORMot2 的日志和扫码结果异步绑定。我在实际项目里的做法是扫码得到字符串后立即创建一个 mORMot2 的TSQLRecord对象并提交到后台线程池后台线程负责 ORM 写入写完之后再Queue回主线程刷新界面。这样不会因为扫码频率高导致 UI 卡顿。7. 经验总结与长期使用建议7.1 控制源码版本mORMot2 迭代非常快GitHub 上的master分支可能每天都有提交。虽然大部分时候是修 bug 或新增功能但也不排除某些 commit 会改变 API 行为。你在生产环境使用最好锁定一个版本而不是永远追最新。像这个 08.03 的包装好之后就把对应源码备份到自己的 Git 库不要随便升级。如果你确实想升级建议先在测试环境把整个单元测试跑一遍。mORMot2 提供了非常完整的单元测试套件在tests目录下。用 Delphi 12.3 打开测试工程跑一遍TTestSuite确认你的目标平台Win64/Linux/Android全绿再合并到主分支。7.2 先建模后编码mORMot2 的开发节奏和传统Dataset开发不太一样。它不是拖控件、拉字段而是先定义业务对象类再由对象驱动数据库表和接口设计。在动手写界面之前你需要把业务实体、属性类型、索引、关联关系先理清楚。比如文章系统你得先想清楚TArticle有哪些字段、哪些需要索引、是否需要全文搜索、标签是一对多还是多对多。这些在类定义阶段定型后期改动会牵连数据库迁移和接口变动。mORMot2 虽然提供了数据库迁移工具但代价还是很高。7.3 不要重复造轮子mORMot2 里已经有TSynLog、TSynTable、TSynCache、TJsonWriter等一堆基础库。很多团队拿到 mORMot2 之后只用它的 ORM其他全部自己写这其实很可惜。用TSynLog替代你自己的日志库、用TSynTable替代你手写的TListT初期可能只是省一点点代码但长期维护时会体会到巨大的便利——因为它们都经过了 mORMot2 的测试套件验证兼容性和性能都有保障。我在实际用 mORMot2 的过程中最大的体会是它把 Delphi 开发从一个“找控件、拼接口”的节奏拉回到了“定义模型、专注业务”的节奏。你不需要再关心底层 HTTP 怎么解析、JSON 怎么转义、SQL 怎么拼接只要把业务类定义好mORMot2 就能把整个链路串起来。这种体验说实话在 Delphi 生态里已经很难得了。如果你还在 Delphi 12.3 上苦于找不到合适的 ORM 或 REST 框架这个控件包值得你花一晚上好好折腾一下。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门