Sequelize是一个关系型数据库ORM框架,它基于Promise构建。支持MySQL、PostgreSQL、MariaDB、SQLite和MSSQL几种关系型数据库,功能非常强大。
1. 介绍与安装
1.1 什么是ORM
ORM(Object Relational Mapping)即:对象关系映射,是随着面向对象的软件开发方法的发展而产生的一种技术。
。对象和关系数据是业务实体的两种表现形式,业务实体在内存中表现为对象,在数据库中表现为关系数据。对象(数据)之间存在关联或继承的,而ORM就是将这些关系映射出来,并通过系统业务逻辑(对象操作)实现对关系数据的管理。
在应用中,我们可能会将数据存放在数据库中。在关系型数据库中,操作和查询数据都要基于SQL语句,这样操作即不直观、又不利于数据管理。而通过ORM技术,将数据库中的关系数据(表结构)映成对象模型和关系模型,这样我们就可以像操作对象一样实现数据库的操作。这时,我们对数据增、删、改、查等操作,都是在ORM中抽像出的一些具体的方法而不再是SQL语句。ORM会自动完成数据层的操作,我们完全不用再写SQL语句,甚至不用关系使用的是MySQL还是其它类型的数据库。
1.2 Sequelize安装
Sequelize本身只是一个ORM框架,它只做了对象模型和关系模型的映射与管理,并没有相关数据库的底层驱动。在使用进,除了要安装sequelize模块外,还要安装所使用数据库的驱动(操作)模块。
安装sequelize:
$ npm install --save sequelize
根据你所使用的数据库类型,安装以下一个数据库驱动模块:
$ npm install --save pg pg-hstore // PostgreSQL时安装
$ npm install --save mysql // MySQL 或 MariaDB 时安装
$ npm install --save sqlite3 // SQLite 时安装
$ npm install --save tedious // MSSQL时安装
2. 连接数据库
Sequelize将设置初始化一个连接池,在应用作用域内,应该为每个数据库创建唯一一个实例。Sequelize()是一个构造函数,通过这个函数可以返回一个Sequelize实例:
var Sequelize = require('sequelize');
var sequelize = new Sequelize(
'my_db, // 数据库名
'root', // 用户名
'secret', // 用户密码
{
'dialect': 'mysql', // 数据库使用mysql
'host': 'localhost', // 数据库服务器ip
'port': 3306 // 数据库服务器端口
}
);
这样就创建了一个连接到MySQL的实例。创建数据库连接有多种形式,可以参考以下格式:
var sequelize = new Sequelize('database', 'username', 'password', {
host: 'localhost',
dialect: 'mysql'|'mariadb'|'sqlite'|'postgres'|'mssql',
pool: {
max: 5,
min: 0,
idle: 10000
},
// 仅 SQLite
storage: 'path/to/database.sqlite'
});
// 也可以通过一个URL创建
var sequelize = new Sequelize('postgres://user:pass@example.com:5432/dbname');
3. 定义对象模型(定义表)
3.1 模型定义
模型是数据库表结构到对象的一种映射关系。可以通过Sequelize实例的sequelize.define()方法来定义模型,其语法结构如下:
sequelize.define('name', {attributes}, {options})
如,定一个user模型:
var User = sequelize.define('user', {
firstName: {
type: Sequelize.STRING, //数据类型
field: 'first_name' // 数据库字段名,即:数据库字段名为'first_name',而对象属性名为'firstName'
},
lastName: {
type: Sequelize.STRING
}
}, {
freezeTableName: true // 模型对应的表名与模型名将相同
});
这样定义了一个名为user的模型对象,这个对象在库中对应表名也是user。在这个对象中有firstName和lastName两个属性,而在对应的表中会相应的生成first_name和lastName两个字段。
3.2 表结构同步
定义模型对象后,对应的表并不能自动创建数据库中,这时还需要调用Model.sync()方法把模型对象同步到数据库表中。如,将上例中的user模型对象同步到数据库中:
User.sync({force: true}).then(function () {
// 表创建完成
return User.create({
firstName: 'John',
lastName: 'Hancock'
});
});
执行完后,数据库my_db将会有一张名为user的表。在上面的同步操作中,还使用Model.create()方法向表中插入了一条数据。
调用Model.sync()方法后,Sequelize会按所使用数据库的语法规则生成创建表的SQL语名,并调用所使用数据库类型的驱动来执行这条语句。在这个方法中,我们使用了force:true参数,这个参数表示首先删除表再重新创建表。
Model.sync()方法并不同必须的,我们也可以先通过数据库对应IDE创建好表结构后,再根据表结构来定义模型对象。如果需要通过Model.sync()方法来同步表结构,一般只需要在创建表或修改表时调用一次,在笔者所应用的项目中是将.sync()表结构同步单独写了一个处理脚本,在初始化或升级时单独调用处理。
3.3 Promise规范API
Sequelize基于Promise进行异步控制,其所有API包括但不限于数据的增、删、改、查操作,其都是基于Promise规范处理。
在Promise规范中,其基于.then()方法得到处理结果,基于.catch()方法进行错误处理。在下面这个操作中:
// 不正确的使用方式
user = User.findOne()
console.log(user.get('firstName'));
这样并不能得到所期望的结果,对象的findOne()方法返回的是一个promise对象(即:user是一个promise对象),而不是数据查询结果。应该像下面这样处理:
User.findOne().then(function (user) {
// 得到结果
console.log(user.get('firstName'));
}).catch(function (err){
// 进行错误处理
console.error(err);
});
4. 对象模型操作(增、删、改、查)
通过Sequelize获取的模型对象实例列是一个DAO(Data Access Object)对象,这些对象会拥有许多操作数据库表的实例对象方法,这个对象会有create()、find()、update()、destroy()等对象操作方法,这些方法会对应的生成INSERT、SELECT、UPDATE、DELETE等SQL语句。
4.1 增:create操作
create操作是指创建数据记录,我们可通过Model.create()方法添加一条数据或通过Model.bulkCreate()方法添加多条数据:
User.create({
firstName: 'liu',
lastName: '小明'
}).then(function (created){
// 创建结果
console.log(created);
}).catch(function(err){
// 出错了
console.log(err);
})
在这个方法,其实际执行SQL语句类似如下:
INSERT INTO `user` (`id`,`first_name`,`lastName`,`createdAt`,`updatedAt`) VALUES (DEFAULT,'liu','小明','2016-05-03 15:22:06','2016-05-03 15:22:06');
可以看出,除了我们在User对象定义时的两个字段外,其还额外处理了id、createdAt、updatedAt三个字段。id是数据表的主键,如果在定义对象时添加了主键,将使用自定义的主键,而没有添加时将自动添加一个名为id的主键。createdAt、updatedAt两个字段同样是自动添加的,如果不需要使用可以在定义模型时进行设置:
sequelize.define('user', {
firstName: {
type: Sequelize.STRING,
field: 'first_name'
},
lastName: {
type: Sequelize.STRING
}
}, {
freezeTableName: true,
'createdAt': false,
'updatedAt': 'utime'
});
更多Model定义参数请参考:Model API。
4.2 改:update操作
update操作是指修改数据记录,我们可通过Model.update()方法来修改已经存在的数据记录:
User.update({firstName:'liu'}, {where:{id:1}}).then(function (result){
// 修改结果
console.log(result);
}).catch(function(err){
// 出错了
console.log(err);
})
在.update()方法中,其实际生成的SQL语句类似如下:
UPDATE `user` SET `first_name`='liu',`updatedAt`='2016-05-03 15:43:32' WHERE `id` = 1
4.3 查:find操作
find操作是指查询已存在的数据记录,我们可通过Model.findOne()方法查找一条数据,或通过Model.findAll()方法查找所有数据:
// 按指定条件查找一条数据
User.findOne({where:{id:1}}).then(function (result){
// 查询结果
console.log(result);
}).catch(function(err){
// 出错了
console.log(err);
})
// 查找所有数据
User.findAll().then(function (result){
// 查询结果
console.log(result);
}).catch(function(err){
// 出错了
console.log(err);
})
在上面的查询操作中,其实际执行SQL语句分别类似如下:
// 单条数据查询
SELECT `id`, `first_name` AS `firstName`, `lastName`, `createdAt`, `updatedAt` FROM `user` AS `user` WHERE `user`.`id` = 1
// 多条数据查询
SELECT `id`, `first_name` AS `firstName`, `lastName`, `createdAt`, `updatedAt` FROM `user` AS `user`
4.4 删:destroy操作
destroy操作是指删除已存在的数据记录,我们可通过Model.destroy()方法来删除数据:
User.destroy({where:{id:1}}).then(function (result){
// 操作结果
console.log(result);
}).catch(function(err){
// 出错了
console.log(err);
})
在以上.destroy()方法中,其实际生成的SQL语句类似如下:
DELETE FROM `user` WHERE `id` = 1