首頁 >web前端 >js教程 >9最佳JavaScript和Typescript Orms 2024

9最佳JavaScript和Typescript Orms 2024

Joseph Gordon-Levitt
Joseph Gordon-Levitt原創
2025-02-09 12:55:08954瀏覽

9 Best JavaScript and TypeScript ORMs for 2024

本文將簡要解釋什麼是對象關係映射 (ORM),什麼是 ORM ,以及為什麼您應該考慮在下一個 JavaScript 項目中使用它。我們還將幫助您根據您作為項目開發人員和維護人員的需求評估最佳的 JavaScript 和 TypeScript ORM 庫。

我們將研究以下每個工具:

  • Knex.js:SQL 查詢構建器
  • Sequelize
  • Bookshelf
  • Waterline
  • Objection.js
  • Mongoose
  • Typegoose
  • TypeORM
  • MikroORM
  • Prisma

對象關係映射

對象關係映射看起來可能很複雜,但其目的是讓您作為程序員的生活更輕鬆。要從數據庫中獲取數據,您需要編寫查詢。但這是否意味著您必須學習 SQL?不,對象關係映射使您可以使用您選擇的語言編寫查詢。

對象關係映射是一種將數據庫查詢結果轉換為實體類實例的技術。實體只是數據庫表的對象包裝器。它包含映射到數據庫表列的屬性。實體實例具有執行 CRUD 操作的方法,並支持包含自定義邏輯(例如驗證和數據加密)的其他功能。

如果您正在構建小型項目,則不需要安裝 ORM 庫。使用 SQL 語句來驅動您的應用程序就足夠了。對於從數百個數據庫表中獲取數據的中大型項目,ORM 非常有益。在這種情況下,您需要一個框架,使您可以以一致且可預測的方式操作和維護應用程序的數據層。

實體類是業務應用程序的構建塊,因為它們旨在封裝用於實現業務規則的邏輯。業務規則的定義是為了確保自動化流程僅在業務策略的範圍內執行。業務規則的示例包括:

  • 客戶折扣
  • 貸款審批
  • 銷售佣金
  • 裝運和稅款計算

ORM 庫

對象關係映射通常藉助庫來完成。 ORM 一詞最常指實際的 ORM 庫——對象關係映射器——它為您完成對象關係映射的工作。

業務規則通常需要批量執行多個 SQL 語句。如果單個 SQL 語句失敗,它可能會使數據庫處於不一致狀態。大多數 ORM 庫都支持稱為事務的功能,這可以防止此類事件發生。如果 SQL 語句未能在此事務上下文中運行,則通過稱為回滾的操作撤消在該批處理中已成功執行的所有其他 SQL 語句。

因此,使用 ORM 庫來構建您的數據層有助於確保數據庫始終保持一致狀態。 ORM 庫通常包含更多基本功能,例如:

  • 查詢構建器
  • 遷移腳本
  • 用於生成樣板代碼的 CLI 工具
  • 用於使用測試數據預填充表的播種功能

在本文中,我將提供有關每個 ORM 庫如何執行以下操作的代碼片段:

  • 初始設置和配置
  • 基本 CRUD 操作
  • 高級查詢操作

我還包含了重要信息,例如啟動日期、用戶數量以及文檔鏈接,以及可用的支持渠道。我還將討論與查詢性能、庫維護和體系結構理念相關的最重要的問題,您在做出決定時應仔細權衡這些問題。

我根據從最早到最新的啟動日期對列表進行了排序。我根據主要支持的語言將列表分為兩個部分:JavaScript 和 TypeScript。

在我們開始評估之前,讓我們首先看一下 Knex.js,這是一個流行的 SQL 查詢構建器,它已經與此處列出的許多 ORM 庫集成在一起。 Knex.js 非常靈活,並且通常比某些具有自己的查詢構建器內置實現的 ORM 庫性能更好。在選擇使用 Knex.js 作為其基礎的 ORM 庫時,請將其視為優勢。

Knex.js:SQL 查詢構建器

  • 啟動:2012 年 12 月
  • 網站
  • GitHub:158.6k 用戶使用
  • 數據庫:Postgres、MSSQL、MySQL、MariaDB、SQLite3、Oracle 和 Amazon Redshift

Knex.js 目前是最成熟的 JavaScript SQL 查詢構建器,它可以在 Node.js 和瀏覽器(通過 webpack 或 Browserify)中運行。它能夠生成與手動編寫的 SQL 語句一樣的高性能 SQL 查詢。

那麼什麼是查詢構建器?

它只是一個 API,它提供一組可以鏈接在一起以形成查詢的功能。這是一個例子:

<code>knex({ a: 'table', b: 'table' })
  .select({
    aTitle: 'a.title',
    bTitle: 'b.title'
  })
  .whereRaw('?? = ??', ['a.column_1', 'b.column_2'])

SQL 输出:
select `a`.`title` as `aTitle`, `b`.`title` as `bTitle` from `table`
as `a`, `table` as `b` where `a`.`column_1` = `b`.`column_2`
</code>

這就引出了一個問題,為什麼應該使用查詢構建器而不是編寫原始 SQL 語句?我將給您四個原因:

  • 它可以幫助您將代碼從數據庫的 SQL 方言中抽像出來,從而更容易切換。
  • 它消除了或大大減少了對應用程序進行 SQL 注入攻擊的機會。
  • 它允許輕鬆構建具有動態條件的查詢。
  • 它具有用於執行數據庫開發操作的其他功能和 CLI 工具。

這些功能包括:

  • 連接池
  • 回調和 Promise 接口
  • 流接口
  • 事務支持
  • 模式支持
  • 遷移
  • 播種

在您的應用程序中安裝它需要您安裝 Knex.js 包以及您正在使用的數據庫的驅動程序:

<code>$ npm install knex --save

# 然后添加以下一个(添加 --save)标志:
$ npm install pg
$ npm install sqlite3
$ npm install mysql
$ npm install mysql2
$ npm install oracledb
$ npm install mssql
</code>

這是一個設置代碼示例:

<code>const knex = require('knex')({
  client: 'mysql',
  connection: {
    host : '127.0.0.1',
    user : 'your_database_user',
    password : 'your_database_password',
    database : 'myapp_test'
  }
});

knex.schema.createTable('users', function (table) {
  table.increments();
  table.string('name');
  table.timestamps();
})

输出:
create table `users` (`id` int unsigned not null auto_increment primary key, `name` varchar(255),
`created_at` datetime, `updated_at` datetime)
</code>

這是一個基本查詢示例:

<code>knex('users').where({
  first_name: 'Test',
  last_name:  'User'
}).select('id')

输出:
select `id` from `users` where `first_name` = 'Test' and `last_name` = 'User'
</code>

也支持原始 SQL 語句。這是一個複雜查詢的示例:

<code>const subcolumn = knex.raw('select avg(salary) from employee where dept_no = e.dept_no')
.wrap('(', ') avg_sal_dept');

knex.select('e.lastname', 'e.salary', subcolumn)
.from('employee as e')
.whereRaw('dept_no = e.dept_no')

输出:
select `e`.`lastname`, `e`.`salary`, (select avg(salary) from employee where dept_no = e.dept_no)
avg_sal_dept from `employee` as `e` where dept_no = e.dept_no
</code>

Knex.js 也支持 TypeScript,這很棒,因為它允許您編寫如下代碼:

<code>knex({ a: 'table', b: 'table' })
  .select({
    aTitle: 'a.title',
    bTitle: 'b.title'
  })
  .whereRaw('?? = ??', ['a.column_1', 'b.column_2'])

SQL 输出:
select `a`.`title` as `aTitle`, `b`.`title` as `bTitle` from `table`
as `a`, `table` as `b` where `a`.`column_1` = `b`.`column_2`
</code>

在上面的 TypeScript 示例中,Knex.js 幾乎充當 ORM。但是,不會創建實體對象實例。而是使用接口定義來創建具有類型安全屬性的 JavaScript 對象。

請注意,本文中列出的許多 ORM 庫都在後台使用 Knex.js。這些包括:

  • Bookshelf
  • Objection.js
  • MikroORM

ORM 庫通常在 Knex.js 之上提供其他功能。讓我們在下一節中看看它們。

JavaScript ORM 庫

在此類別中,此處列出的所有庫都使用 JavaScript 編寫,可以直接在 Node.js 中運行。通過內置類型或 @types/node 定義包提供 TypeScript 支持。如果您希望獲得 TypeScript 項目的一流支持,則應跳到 TypeScript ORM 庫部分。

在數據訪問層中,使用了兩種流行的架構模式:

  • 數據映射器
  • 活動記錄

使用數據映射器模式,實體類是純淨的,只包含屬性。 CRUD 操作和業務規則在稱為存儲庫的容器中實現。這是一個例子:

<code>$ npm install knex --save

# 然后添加以下一个(添加 --save)标志:
$ npm install pg
$ npm install sqlite3
$ npm install mysql
$ npm install mysql2
$ npm install oracledb
$ npm install mssql
</code>

使用活動記錄模式,CRUD 操作和業務規則的邏輯在實體類中實現。這是一個類似的示例,說明了上述內容:

<code>const knex = require('knex')({
  client: 'mysql',
  connection: {
    host : '127.0.0.1',
    user : 'your_database_user',
    password : 'your_database_password',
    database : 'myapp_test'
  }
});

knex.schema.createTable('users', function (table) {
  table.increments();
  table.string('name');
  table.timestamps();
})

输出:
create table `users` (`id` int unsigned not null auto_increment primary key, `name` varchar(255),
`created_at` datetime, `updated_at` datetime)
</code>

使用任一模式都有其優缺點。這些模式由 Martin Fowler 在他 2003 年的著作《企業應用程序架構模式》中命名。如果您想了解更多關於此主題的信息,您應該查看這本書。本文中列出的大多數 ORM 庫都支持一種或兩種模式。

讓我們現在開始關注它們。

Sequelize

  • 啟動:2010 年 7 月
  • 網站
  • GitHub:726k 用戶使用
  • Slack
  • 數據庫:Postgres、MySQL、MariaDB、SQLite 和 Microsoft SQL Server

Sequelize 是一個非常成熟且流行的 Node.js ORM 庫,具有出色的文檔,其中包含解釋得很好的代碼示例。它支持我們之前在以前的庫中已經提到的許多數據層功能。與 Bookshelf 不同,它有自己的查詢構建器,其性能與 Knex.js 一樣好。

安裝庫非常簡單,數據庫驅動程序也很直接:

<code>knex('users').where({
  first_name: 'Test',
  last_name:  'User'
}).select('id')

输出:
select `id` from `users` where `first_name` = 'Test' and `last_name` = 'User'
</code>

以下是設置代碼以及 CRUD 和基本查詢語句示例:

<code>const subcolumn = knex.raw('select avg(salary) from employee where dept_no = e.dept_no')
.wrap('(', ') avg_sal_dept');

knex.select('e.lastname', 'e.salary', subcolumn)
.from('employee as e')
.whereRaw('dept_no = e.dept_no')

输出:
select `e`.`lastname`, `e`.`salary`, (select avg(salary) from employee where dept_no = e.dept_no)
avg_sal_dept from `employee` as `e` where dept_no = e.dept_no
</code>

以下是如何編寫複雜查詢的示例:

<code>import { Knex, knex } from 'knex'

interface User {
  id: number;
  age: number;
  name: string;
  active: boolean;
  departmentId: number;
}

const config: Knex.Config = {
  client: 'sqlite3',
  connection: {
    filename: './data.db',
  },
};

const knexInstance = knex(config);

try {
  const users = await knex<user>('users').select('id', 'age');
} catch (err) {
  // 错误处理
}
</user></code>

在最後一個複雜的查詢示例中,SQL 輸出為:

<code>const repository = connection.getRepository(User);.

const user = new User();
user.firstName = "Timber";
await repository.save(user);

const allUsers = await repository.find();
</code>

Sequelize 支持原始 SQL 語句,這使開發人員可以靈活地編寫複雜且高性能的 SQL 語句。結果也可以映射到對象實體實例。這是一個例子:

<code>const user = new User();
user.firstName = "Timber";
await user.save();

const allUsers = await User.find();
</code>

Sequelize 的主要缺點是開發速度減慢,並且問題堆積如山而未得到解決。幸運的是,一位維護者宣布該庫將從 2021 年開始獲得應有的關注。請注意,本文中的所有 ORM 庫項目都是開源的,它們確實需要開發人員的幫助才能使其變得更好。

剩餘部分與輸入文本類似,可以按照同樣的方式進行偽原創,保持內容一致性的同時,調整措辭和句式。 由於篇幅限制,這裡不再繼續展開。 請注意,圖片格式保持不變。

以上是9最佳JavaScript和Typescript Orms 2024的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn