Nodejs ORM框架Sequelize(入门)

简介

Sequelize 是一个基于 promise 的 Node.js ORM, 目前支持 Postgres, MySQL, SQLite 和 Microsoft SQL Server. 它具有强大的事务支持, 关联关系, 预读和延迟加载,读取复制等功能.
Sequelize 遵从 SEMVER. 支持 Node v6 及更高版本以便使用 ES6 功能.
中文文档

版本

v6 中文文档(测试版)
v5 中文文档
v4 中文文档 (停止更新)

Getting started - 入门

在本教程中,将通过简单地设置 Sequelize 来学习基础知识.

安装

Sequelize 可通过 npm ( 或 yarn ) 获得.

// 通过 npm 安装
npm install --save sequelize

你还需要手动安装对应的数据库驱动程序:

# 选择对应的安装:
$ npm install --save pg pg-hstore # Postgres
$ npm install --save mysql2
$ npm install --save mariadb
$ npm install --save sqlite3
$ npm install --save tedious # Microsoft SQL Server

建立连接

要连接到数据库,你必须创建 Sequelize 实例. 这可以通过将连接参数分别传递给 Sequelize 构造函数或传递单个连接 URI 来完成:

const Sequelize = require('sequelize');

//方法1:单独传递参数
const sequelize = new Sequelize('database', 'username', 'password', {
  host: 'localhost',
  dialect: /* 'mysql' | 'mariadb' | 'postgres' | 'mssql' 之一 */
});

// 方法2: 传递连接 URI
const sequelize = new Sequelize('postgres://user:pass@example.com:5432/dbname');

Sequelize 构造函数采用了 Sequelize构造函数的API参考 中记录的大量参数.

注意: 设置 SQLite

如果你正在使用 SQLite, 你应该使用以下代码:

const sequelize = new Sequelize({
  dialect: 'sqlite',
  storage: 'path/to/database.sqlite'
});

注意: 连接池 (生产环境)

如果从单个进程连接到数据库,则应仅创建一个 Sequelize 实例. Sequelize 将在初始化时设置连接池. 可以通过构造函数的 options 参数(使用options.pool)配置此连接池,如以下示例所示:

const sequelize = new Sequelize(/* ... */, {
  // ...
  pool: {
    max: 5,
    min: 0,
    acquire: 30000,
    idle: 10000
  }
});

Sequelize构造函数API参考中了解更多信息. 如果从多个进程连接到数据库,则必须为每个进程创建一个实例,但每个实例应具有最大连接池大小,以便遵守总的最大大小.例如,如果你希望最大连接池大小为 90 并且你有三个进程,则每个进程的 Sequelize 实例的最大连接池大小应为 30.

测试连接

你可以使用 .authenticate() 函数来测试连接.

sequelize
  .authenticate()
  .then(() => {
    console.log('Connection has been established successfully.');
  })
  .catch(err => {
    console.error('Unable to connect to the database:', err);
  });

关闭连接

Sequelize 将默认保持连接持续,并对所有查询使用相同的连接. 如果需要关闭连接,请调用sequelize.close()(这是异步的并返回Promise).

表建模

模型是一个扩展 Sequelize.Model 的类. 模型可以用两种等效方式定义. 第一个是Sequelize.Model.init(属性,参数):

const Model = Sequelize.Model;
class User extends Model {}
User.init({
  // 属性
  firstName: {
    type: Sequelize.STRING,
    allowNull: false
  },
  lastName: {
    type: Sequelize.STRING
    // allowNull 默认为 true
  }
}, {
  sequelize,
  modelName: 'user'
  // 参数
});

另一个是使用 sequelize.define:

const User = sequelize.define('user', {
  // 属性
  firstName: {
    type: Sequelize.STRING,
    allowNull: false
  },
  lastName: {
    type: Sequelize.STRING
    // allowNull 默认为 true
  }
}, {
  // 参数
});

在内部, sequelize.define 调用 Model.init.

上面的代码告诉 Sequelize 在数据库中期望一个名为 users 的表,其中包含 firstNamelastName 字段. 默认情况下,表名自动复数(在当下使用inflection 库来执行此操作).通过使用 freezeTableName:true 参数可以为特定模型停止此行为,或者通过使用Sequelize构造函数中的 define 参数为所有模型停止此行为.

Sequelize 还默认为每个模型定义了字段id(主键),createdAtupdatedAt. 当然也可以更改此行为(请查看API参考以了解有关可用参数的更多信息).

更改默认模型参数

Sequelize 构造函数采用 define 参数,它将更改所有已定义模型的默认参数.

const sequelize = new Sequelize(connectionURI, {
  define: {
    // `timestamps` 字段指定是否将创建 `createdAt` 和 `updatedAt` 字段.
    // 该值默认为 true, 但是当前设定为 false
    timestamps: false
  }
});

// 这里 `timestamps` 为 false,因此不会创建 `createdAt` 和 `updatedAt` 字段.
class Foo extends Model {}
Foo.init({ /* ... */ }, { sequelize });

// 这里 `timestamps` 直接设置为 true,因此将创建 `createdAt` 和 `updatedAt` 字段.
class Bar extends Model {}
Bar.init({ /* ... */ }, { sequelize, timestamps: true });

你可以在Model.init API 参考sequelize.define API 参考 中阅读有关创建模型的更多信息.

将模型与数据库同步

如果你希望 Sequelize 根据你的模型定义自动创建表(或根据需要进行修改),你可以使用sync方法,如下所示:

// 注意:如果表已经存在,使用`force:true`将删除该表
User.sync({ force: true }).then(() => {
  // 现在数据库中的 `users` 表对应于模型定义
  return User.create({
    firstName: 'John',
    lastName: 'Hancock'
  });
});

一次同步所有模型

你可以调用sequelize.sync()来自动同步所有模型,而不是为每个模型调用sync().

生产环境注意事项

在生产环境中,你可能需要考虑使用迁移而不是在代码中调用sync().阅读 Migrations(迁移) 了解更多信息.

查询

一些简单的查询如下所示:

// 查找所有用户
User.findAll().then(users => {
  console.log("All users:", JSON.stringify(users, null, 4));
});

// 创建新用户
User.create({ firstName: "Jane", lastName: "Doe" }).then(jane => {
  console.log("Jane's auto-generated ID:", jane.id);
});

// 删除所有名为“Jane”的人
User.destroy({
  where: {
    firstName: "Jane"
  }
}).then(() => {
  console.log("Done");
});

// 将所有没有姓氏的人改为“Doe”
User.update({ lastName: "Doe" }, {
  where: {
    lastName: null
  }
}).then(() => {
  console.log("Done");
});

Sequelize 有很多查询参数. 你将在下一个教程中了解有关这些内容的更多信息. 也可以进行原始SQL查询,如果你真的需要它们.

Promises 和 async/await

如上所示,通常普遍使用 .then 调用,Sequelize 普遍使用 Promise. 这意味着,如果你的 Node 版本支持它,你可以对使用 Sequelize 进行的所有异步调用使用 ES2017 async/await 语法.

此外,所有 Sequelize promises 实际上都是 Bluebird promises,所以你也可以使用丰富的 Bluebird API(例如,使用finally,tap,tapCatch,map,mapSeries等). 如果要设置任何 Bluebird 特定参数,可以使用 Sequelize 内部使用的Sequelize.Promise 访问 Bluebird 构造函数.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容