Node.js自研ORM框架深度解析與實踐

Node.js自研ORM框架深度解析與實踐

前言

在現代Web開發中,對象關系映射(ORM)框架扮演著至關重要的角色。它們為開發者提供了一層抽象,使得數據庫操作變得更加簡單和直觀。本文將深入解析一個基于Node.js和MySQL的自研ORM框架,該框架雖然輕量級,但功能完善,包含了連接池管理、查詢構建器、事務處理、字段驗證等核心功能。

項目概述

技術棧

  • 運行環境: Node.js
  • 數據庫: MySQL
  • 核心依賴: mysql@2.18.1

項目結構

Node/
├── orm/                    # ORM核心模塊
│   ├── db.js              # 數據庫連接與事務處理
│   ├── dbSet.js           # 數據集操作(CRUD)
│   └── QueryBuilder.js    # SQL查詢構建器
├── entitys/               # 實體層
│   └── dbContext.js       # 數據庫上下文
├── dbtest.js              # 測試文件
└── package.json           # 項目配置

核心模塊深度解析

1. 數據庫連接層 (db.js)

數據庫連接層是整個ORM框架的基礎,負責管理MySQL連接池和事務處理。

核心特性
  • 連接池管理: 使用mysql.createPool()創建連接池,提高性能
  • 異步操作: 基于Promise封裝,支持async/await語法
  • 事務支持: 完整的事務生命周期管理(開啟、提交、回滾)
  • 錯誤處理: 完善的異常捕獲和處理機制
關鍵代碼解析
// 連接池初始化
function DbBase(options) {this.pool = mysql.createPool(options);
}// 核心查詢方法
DbBase.prototype.Run = async function (sql, params, conn) {if (conn) {// 使用指定連接(事務場景)return new Promise((resolve, reject) => {conn.query(sql, params, (err, result) => {if (err) {console.log(err);reject(err);} else {resolve(result);}});});} else {// 使用連接池return new Promise((resolve, reject) => {this.pool.query(sql, params, (err, result) => {if (err) {console.log(err);reject(err);} else {resolve(result);}});});}
};
事務處理機制

事務處理是這個ORM框架的亮點之一,實現了完整的事務生命周期:

DbBase.prototype.RunTransaction = async function (fn) {let connection;try {// 1. 獲取連接connection = await new Promise((resolve, reject) => {this.pool.getConnection((err, conn) => {if (err) reject(err);else resolve(conn);});});// 2. 開啟事務await new Promise((resolve, reject) => {connection.beginTransaction(err => {if (err) reject(err);else resolve();});});// 3. 執行業務邏輯const result = await fn(connection);// 4. 提交事務await new Promise((resolve, reject) => {connection.commit(err => {if (err) {connection.rollback(() => {reject(err);});} else {resolve(result);}});});return result;} catch (error) {// 5. 異常回滾if (connection) {await new Promise((resolve, reject) => {connection.rollback(() => {connection.release();reject(error);});});}} finally {// 6. 釋放連接if (connection) {connection.release();}}
};

2. 查詢構建器 (QueryBuilder.js)

查詢構建器采用鏈式調用模式,提供了靈活的SQL構建能力。

核心特性
  • 鏈式調用: 支持method chaining模式
  • 參數化查詢: 防SQL注入
  • 分頁支持: 內置分頁功能
  • 靈活的條件構建: 支持多種WHERE條件
使用示例
// 基礎查詢
const query = new QueryBuilder().select(['id', 'name', 'email']).from('users').where('status', 'active').where('age', '>', 18).orderBy('created_at', 'DESC').paginate(1, 10);const {sql, parameters} = query.build();
分頁功能實現
paginate(page, perPage) {if(page <= 1) page = 1;const offset = (page - 1) * perPage;return this.limit(offset, perPage);
}

3. 數據集操作層 (dbSet.js)

dbSet是ORM框架的核心,實現了完整的CRUD操作和數據驗證功能。

核心功能
  • CRUD操作: Create、Read、Update、Delete
  • 字段驗證: 類型、長度、必填、默認值驗證
  • 自動主鍵: 支持自增主鍵
  • 視圖支持: 區分表和視圖的操作權限
字段定義與驗證
// 字段定義
dbSet.prototype.AddField = function (fieldName, fieldType, length = 0, required = false, isNull = true, defaultValue = null) {this.fields[fieldName] = { fieldName, fieldType, length, required, isNull, defaultValue };
}// 字段驗證邏輯
dbSet.prototype.FieldVerify = function (data) {Object.keys(this.fields).forEach(key => {var field = this.fields[key];var fieldValue = data[field.fieldName];// 必填驗證if (field.required && !(field.fieldName in data)) throw new Error(`必須包含字段'${field.fieldName}'`);// 默認值設置if (field.defaultValue != null && fieldValue == null) data[field.fieldName] = field.defaultValue;});// 類型驗證、長度驗證等...
};
CRUD操作實現

添加數據

dbSet.prototype.Add = async function (data, conn) {if (this.isview) {throw new Error(`視圖${this.tableName}不能添加數據`);}this.FieldVerify(data);var { keys, values, _values } = this.GetDataContent(data);var sql = `insert into \`${this.tableName}\`(${keys}) values(${_values})`;return new Promise((resolve, reject) => {this.db.Run(sql, values, conn).then(res => {resolve(res.insertId);}).catch(err => {reject(err);});});
}

查詢數據

dbSet.prototype.GetList = async function (query, conn) {var { sql, parameters } = query.build();return new Promise((resolve, reject) => {this.db.Run(sql, parameters, conn).then(res => {resolve(res);}).catch(err => {reject(err);})})
}
性能優化特性

連接復用查詢

dbSet.prototype.GetTable = async function(query) {// 使用同一個連接進行列表和計數查詢,節約連接池開銷let connection;try {connection = await new Promise((resolve, reject) => {this.db.pool.getConnection((err, conn) => {if (err) reject(err);else resolve(conn);});});var list = await this.GetList(query, connection);var count = await this.GetCount(query, connection);return {list, count};} finally {if (connection) connection.release();}
}

4. 數據庫上下文 (dbContext.js)

數據庫上下文是整個ORM框架的入口點,負責初始化數據庫連接和實體映射。

function dbContext() {// 數據庫連接配置this.db = new DbBase({host: '127.0.0.1',port: '3306',user: 'user',password: '123456',database: 'test'});// 實體映射this.test = new dbSet("test", this.db);this.test.AddField("name", "string", 3, true, false, "123456");
}

實戰測試案例

基礎CRUD操作測試

var dbContext = require('./entitys/dbContext');
var _db = new dbContext();// 添加數據
var res = await _db.test.Add({name: "測試用戶"
});
console.log("新增ID:", res);// 查詢數據
var query = _db.test.Query();
query.where("id", 5);
query.limit(100);
var result = await _db.test.GetTable(query);
console.log("查詢結果:", result);

事務操作測試

// 事務示例
await _db.db.RunTransaction(async (conn) => {// 在事務中執行多個操作var res1 = await _db.test.Add({name: "事務測試1"}, conn);var res2 = await _db.test.Add({name: "事務測試2"}, conn);// 如果任何操作失敗,整個事務會自動回滾
});

框架特色與優勢

1. 輕量級設計

  • 核心代碼不到500行
  • 無重度依賴,僅依賴mysql驅動
  • 啟動快速,內存占用低

2. 類型安全

  • 完整的字段類型驗證
  • 數據長度校驗
  • 必填字段檢查

3. 性能優化

  • 連接池管理
  • 參數化查詢防止SQL注入
  • 連接復用減少開銷

4. 易于擴展

  • 模塊化設計
  • 清晰的分層架構
  • 支持自定義字段類型

與主流ORM框架對比

特性自研ORMSequelizeTypeORM
學習成本
性能
功能完整性基礎完整完整
包大小極小
定制性

應用場景

適用場景

  • 中小型項目快速開發
  • 對性能要求較高的場景
  • 需要深度定制ORM功能
  • 學習ORM原理的教學項目

不適用場景

  • 復雜的關系映射需求
  • 需要數據庫遷移功能
  • 多數據庫支持需求

總結

這個自研ORM框架雖然功能相對簡單,但展現了ORM框架的核心設計思想:

  1. 分層架構: 清晰的數據庫連接層、查詢構建層、數據操作層
  2. 事務管理: 完整的事務生命周期處理
  3. 性能優化: 連接池、參數化查詢等優化策略
  4. 類型安全: 完善的數據驗證機制

對于中小型項目或學習ORM原理來說,這是一個很好的參考實現。通過理解這個框架的設計思路,開發者可以更好地理解ORM的工作原理,并根據實際需求進行擴展和優化。

在實際項目中,建議根據具體需求選擇合適的ORM框架。如果項目規模較小且對性能要求較高,可以考慮使用類似的輕量級自研方案;如果項目復雜度較高,則建議選擇成熟的開源ORM框架如Sequelize或TypeORM。


本文詳細解析了一個基于Node.js的自研ORM框架,涵蓋了數據庫連接、查詢構建、CRUD操作、事務處理等核心功能。希望能夠為正在學習或考慮自研ORM框架的開發者提供有價值的參考。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/94341.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/94341.shtml
英文地址,請注明出處:http://en.pswp.cn/web/94341.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

匯總圖片拖進ps中 photoshop同時打開幾個文件夾

如果你有許多文件夾&#xff0c;你想選中一部分&#xff0c;然后把里面的圖片全部拖進photoshop當中&#xff0c;但是文件夾又不能直接拖進去&#xff0c;那么你可以嘗試使用一下這個工具&#xff0c;首先測試一下直接拖文件夾。選中你要處理的文件夾&#xff0c;直接拖進photo…

mysql 5.7 查詢運行時間較長的sql

開發過程遇到sql 執行時間長&#xff0c;又取消不了的情況 可使用 kill query ID 殺死進程獲取正在運行的sqlSELECT ID, -- 進程ID&#xff1a;MySQL服務器分配給每個連接的唯一標識符&#xff0c;用于區分不同的客戶端連接USER, …

MongoDB 從入門到實踐:全面掌握文檔型 NoSQL 數據庫核心操作

目錄 一、MongoDB 基礎準備 1. 官方資源獲取 2. 安裝步驟解析 二、MongoDB 核心指令詳解 1. 數據庫操作指令 2. 集合操作指令 3. 文檔操作指令 查詢文檔 插入文檔 修改文檔 刪除文檔 三、進階查詢技巧 1. 運算符的靈活運用 比較運算符 邏輯運算符 范圍與成員運算…

CVPR2025丨遙感領域,全模態與秒超高清遙感建模重大突破,性能提升創新點

關注gongzhonghao【CVPR頂會精選】剛入門遙感建模時&#xff0c;總好奇別人為什么總能提出新方法&#xff1f;慢慢摸索后才發現&#xff0c;創新點并不是硬憋出來的&#xff0c;而是要從數據特性、傳感器差異、地物細節以及環境變化中發現機會。不同波段、不同分辨率、不同時相…

HTML5詳篇

前端三劍客 前端三劍客是指HTML、CSS和JavaScript: HTML超文本標記語言(Hyper Text Markup Language):簡單理解描述網頁結構的;用于網頁內容的語言。它通過使用不同的HTML標簽來定義頁面中的各種元素,例如標題、段落、圖像、鏈接等【無羽毛的小鳥模型】 CSS層疊樣式表(…

【Transient-Free 3DGS】delayed densification + coarse to fine增加GS的魯棒性

25年最新連接去除場景瞬態對象工程與3DGS的pipeline&#xff0c;改進了spotlesssplats&#xff0c;已開源&#xff1a; [2506.02751] RobustSplat: Decoupling Densification and Dynamics for Transient-Free 3DGSAbstract page for arXiv paper 2506.02751: RobustSplat: De…

【MySQL】CRUD基礎詳解

CRUD基礎前言&#xff1a;數據庫的層級結構一、新增&#xff08;Create&#xff09;1. 單行數據 全列插入2. 單行數據的簡寫插入3. 指定列插入4. 多行數據插入二、查詢&#xff08;Retrieve&#xff09;1. 全列查詢2. 指定列查詢3. 查詢結果為表達式&#xff08;1&#xff09;…

互聯網大廠Java求職面試實錄:核心技術棧與業務場景解析

互聯網大廠Java求職面試實錄&#xff1a;核心技術棧與業務場景解析 面試場景設定 本文通過一個嚴肅的面試官和搞笑的水貨程序員大面條之間的對話&#xff0c;模擬互聯網大廠Java崗位的技術面試過程。面試涵蓋Java SE、Spring生態、數據庫、微服務、緩存、安全、消息隊列、AI等多…

response對象的elapsed屬性

在Python的requests庫中&#xff0c;當我們發送一個請求后&#xff0c;會得到一個Response對象&#xff0c;這個對象有一個elapsed屬性&#xff0c;它返回一個timedelta對象&#xff0c;表示從發送請求到收到響應所經過的時間。response.elapsed.total_seconds() 是 Python req…

【ansible】5.在受管主機部署文件和Jinja2模板

1.Ansible 中&#xff0c;如何用模塊創建一個文件并設置權限644并設置SELinux類型&#xff0c;如何從受管主機中刪除文件&#xff1f;使用ansible.builtin集合中的 file 模塊&#xff0c;添加state&#xff1a;touch 創建文件&#xff0c;mode&#xff1a;‘0644’ 設置權限&am…

雪花算法數據庫主鍵

雪花算法&#xff08;Snowflake&#xff09;作為一種分布式 ID 生成方案&#xff0c;在分布式系統中具有顯著優勢&#xff0c;能夠解決多個關鍵問題。以下是它的核心好處及主要應用場景&#xff1a;雪花算法的核心好處全局唯一性&#xff1a;通過時間戳、機器 ID、數據中心 ID …

C/C++ 頭文件命名約定

有的時候&#xff0c;在C的代碼中&#xff0c;可以看到有如下的頭文件引用的代碼: #include <iostream> #include <unistd.h> #include <csignal>其中有一些是引用了.h文件&#xff0c;另外一些是引用了模塊式的比如iostream和csignal&#xff0c;那么為什么…

異質結3.0時代的降本提效革命:捷造科技設備技術創新與產業拐點分析

光伏產業經歷了從PERC到TOPCon和異質結&#xff08;HJT&#xff09;的技術迭代&#xff0c;而2025年將成為異質結技術規模化應用的關鍵轉折點。捷造科技通過一系列突破性技術創新&#xff0c;將GW級異質結整線設備價格降至2億元&#xff0c;較行業平均水平降低約40%&#xff0c…

【網絡】http 協議中 Vary 標頭的作用

在 HTTP 協議中&#xff0c;Vary 標頭是一個關鍵的緩存控制機制&#xff0c;用于告知緩存服務器&#xff08;或代理&#xff09;&#xff1a;響應內容的生成依賴于請求中的哪些特定頭部字段。其核心作用是確保緩存服務器能根據這些字段的差異&#xff0c;正確區分和返回不同版本…

CSS 進階用法

一、選擇器進階復雜選擇器組合詳解后代選擇器后代選擇器使用空格分隔兩個選擇器&#xff0c;例如div p&#xff0c;表示選擇div元素內所有的p元素。這種選擇方式會匹配所有層級的后代元素&#xff0c;包括子元素、孫元素等任意深度的嵌套元素。應用示例&#xff1a;/* 選中arti…

GitHub 熱榜項目 - 日榜(2025-08-23)

GitHub 熱榜項目 - 日榜(2025-08-23) 生成于&#xff1a;2025-08-23 統計摘要 共發現熱門項目&#xff1a;13 個 榜單類型&#xff1a;日榜 本期熱點趨勢總結 本期GitHub熱榜呈現三大技術熱點&#xff1a;1&#xff09;AI工作流構建成為風口&#xff0c;sim和airi等項目展示…

SHAP分析+KOA-RIME開普勒結合霜冰算法雙重優化BP神經網絡+9種映射方法+新數據預測!機器學習可解釋分析!

代碼主要功能 該Matlab代碼實現了一個KOA-RIME開普勒結合霜冰算法雙重優化的BP神經網絡回歸模型&#xff0c;結合特征貢獻度分析&#xff08;SHAP&#xff09;和新數據預測功能。核心功能包括&#xff1a; 雙重參數優化&#xff1a;先用智能算法&#xff08;以chebyshev映射改進…

【數據結構】棧和隊列——棧

目錄棧和隊列棧棧的基本概念棧的順序存儲實現棧的定義與初始化入棧操作出棧操作讀取棧頂元素判空和判滿操作棧的銷毀操作操作集合棧和隊列 棧 棧的基本概念 棧的定義&#xff1a; 棧&#xff08;Stack&#xff09; 是一種線性表&#xff0c;它限定了數據元素的插入和刪除操…

大數據管理與應用系列叢書《數據挖掘》讀書筆記之集成學習(1)

文章目錄前言一、集成學習是什么&#xff1f;1.基本思想2.集成學習的類型3. 集成學習的結合策略3.1 為什么結合策略是集成學習的靈魂&#xff1f;3.2 經典策略(1)**投票法&#xff08;Voting&#xff09;****(2)平均法&#xff08;Averaging&#xff09;****(3) 學習法**3.3 關…

嵌入式知識篇---32GUI

要理解 32 位單片機的 GUI&#xff0c;咱們先從 “基礎概念” 入手&#xff0c;再拆成 “為什么能跑 GUI”“核心組成”“怎么實現”“常用工具”“實際用途” 這幾步講&#xff0c;全程不用復雜術語&#xff0c;像聊日常用品一樣說清楚。一、先搞懂 2 個基礎概念在講 “32 位單…