入门指南
http://sequelizejs.com/articles/getting-started
简介
本文主要介绍Sequelize的一些基础概念,并将学习一些关于数据库设置,数据访问常用场景的编写方式。
前言
我们将跳过一些基础内容,直接开始介绍Sequelize的一些内容。在我们开始之前,需要做如下准备:
-
Node.js V0.8 以上版本
-
一个数据库/SQLite
-
数据库的使用授权
-
了解数据库的运行方式
-
可以选择准备一杯咖啡 :)
建立项目
如果你的电脑和咖啡都准备好了,我们就可以开始启动了。
第一步:我需要建立一个目录,并通过NPM将其初始化。
mkdir my-project
cd my-projectnpm
init
NPM会询问一些问题,可以直接回车直到结束。接下来,可以开始安装Sequelize,以及所选择的数据库连接组件库。
npm install --save sequelize
npm install --save pg # for postgres
npm install --save mysql # for mysql
npm install --save sqlite3 # for sqlite
npm install --save mariasql # for mariasql
连接数据库
打开你所喜欢的文本编辑器,建立一个名为app.js文件,添加一下内容:
var Sequelize = require('sequelize')
, sequelize = new Sequelize('database_name', 'username', 'password', {
dialect: "mysql", // or 'sqlite', 'postgres', 'mariadb'
port: 3306, // or 5432 (for postgres)
})
sequelize
.authenticate()
.complete(function(err) {
if (!!err) {
console.log('Unable to connect to the database:', err)
} else {
console.log('Connection has been established successfully.')
}
})
管理数据库的Schema
Sequelize支持两种Schema的管理方式,你可以通过一种被称为migrations的程序化的方式改变数据库的结构,或者使用Sequelize来为你创建数据库表。
如果你需要将应用部署至众多不同的服务器环境,migrations方式会是你的必选,虽然它会在配置过程中耗掉大量的时间。
以上究其原因,migrations会根据Schema当前的状态来保持你数据库的一致性。
然而,使用Sequelize的sequelize.sync功能的自动化方式更适用用于你的本机或快速构建原型。
定义一个模型
在数据库中创建一个Schema,首先得描述需要创建的数据类型,可以使用sequelize.define,如下:
var User = sequelize.define('User', {
username: Sequelize.STRING,
password: Sequelize.STRING
})
这将在user模型中定义username,password两列属性,此外,Sequelize还会自动添加id,createdAt,updatedAt三列属性。
同步Schema
我们需要在数据库中存储数据,那我们就需要在数据库中建立模型对应的表。
sequelize
.sync({ force: true })
.complete(function(err) {
if (!!err) {
console.log('An error occurred while creating the table:', err)
} else {
console.log('It worked!')
}
})
执行后,数据库中user表会加入以下数据列:
-
id - INT(11)
-
username - VARCHAR(255)
-
password - VARCHAR(255)
-
createdAt - DATETIME
-
updatedAt - DATETIME
需要注意的是,
{ force: true }
将会删除所有表后,之后再进行重建。
配置
你可能也不需要以上timestamps数据列,或者并不希望模型的名称与数据表的名称一致,那我们这样设置:
var User = sequelize.define('User', {
username: Sequelize.STRING,
password: Sequelize.STRING
}, {
tableName: 'my_user_table', // this will define the table's name
timestamps: false // this will deactivate the timestamp columns
})
如果希望自行定义timestamps的名称,可以做下面的设置:
var User = sequelize.define('User', {
username: Sequelize.STRING,
password: Sequelize.STRING
}, {
tableName: 'my_user_table', // this will define the table's name
timestamps: false // this will deactivate the timestamp columns
})
创建并持久化实例
Sequelize允许两种创建实例的方式,你可以先build一个对象,然后在save;或者直接create进入数据库。
var user = User.build({
username: 'john-doe',
password: generatePasswordHash('i-am-so-great')
})
user
.save()
.complete(function(err) {
if (!!err) {
console.log('The instance has not been saved:', err)
} else {
console.log('We have a persisted instance now')
}
})
以上存储一个实例需要使用两步,如果你希望一次完成,可以按照下面方式操作:
User
.create({
username: 'john-doe',
password: generatePasswordHash('i-am-so-great')
})
.complete(function(err, user) {
/* ... */
})
读取数据
每个定义的model都有一些查询方法,用来读取数据内容。查询特定的数据,可以使用Model.find;也可以使用Model.findAll查询多条数据。
User
.find({ where: { username: 'john-doe' } })
.complete(function(err, johnDoe) {
if (!!err) {
console.log('An error occurred while searching for John:', err)
} else if (!johnDoe) {
console.log('No user with the username "john-doe" has been found.')
} else {
console.log('Hello ' + johnDoe.username + '!')
console.log('All attributes of john:', johnDoe.values)
}
})
请注意,如果没有找到'john-doe',也不会有错误;
依赖定义
一个常见的用例就是定义两个或多个model之间的联系。声明关联关系后,Sequelize将会知道如何get/set相关联的数据。甚至可以自动创建各自相应的外键数据列。
再看代码之前,我们先了解一下这三种关联关系的一些细节内容。
one to one
源对象与目标对象是1对1的关系。一个源对象拥有一个目标对象,一个目标对象从属于一个源对象。
Sequelize认为外键在目标对象映射的数据表中,这就意味着目标对象表中需要有描述外键的列属性。
var Source = sequelize.define('Source', {})
, Target = sequelize.define('Target', {})
Source.hasOne(Target)
Target.belongsTo(Source)
sequelize
.sync({ force: true })
.complete(function(err) {
// Even if we didn't define any foreign key or something else,
// instances of Target will have a column SourceId!
})
one to many
一对多关系,一个源对象包含多个目标对象,多个目标对象从属于一个源对象。
Sequelize认为外键在目标对象映射的数据表中,这就意味着目标对象表中需要有描述外键的列属性。
var Source = sequelize.define('Source', {})
, Target = sequelize.define('Target', {})
Source.hasMany(Target)
Target.belongsTo(Source)
sequelize
.sync({ force: true })
.complete(function(err) {
// Even if we didn't define any foreign key or something else,
// instances of Target will have a column SourceId!
})
many to many
多对多关系。
Sequelize中期望有中间关联表,用于记录源对象的外键与目标对象的外键。
var Source = sequelize.define('Source', {})
, Target = sequelize.define('Target', {})
Source.hasMany(Target)
Target.hasMany(Source)
sequelize
.sync({ force: true })
.complete(function(err) {
// Even if we didn't define any foreign key or something else,
// Sequelize will create a table SourcesTargets.
})
Getting/Setting 关联关系
定义关联很容易,如果不读取或设置这种关联,定义不会有任何作用。
当然models中也会添加入相应的方法,不同的关联关系也会有不同的方法,如下:
var Source = sequelize.define('Source', {})
, Target = sequelize.define('Target', {})
Source.hasOne(Target)
Target.belongsTo(Source)
Source.create({}).complete(function(err, source) {
Target.create({}).complete(function(err, target) {
// Set the association
source.setTarget(target).complete(function(err) {
// Get the association
source.getTarget().complete(function(err, _target) {
console.log(_target.values)
/*
{
id: 1,
createdAt: Sun Dec 08 2013 11:46:42 GMT+0100 (CET),
updatedAt: Sun Dec 08 2013 11:46:42 GMT+0100 (CET),
SourceId: 1
}
*/
})
})
})
})
清除关联关系
假设我们已经定义的模型(比如前面的代码示例)和同步数据库的Schema,我们可以这样清除关联关系:
source.setTarget(null).complete(function(err) {
source.getTarget().complete(function(err, target) {
console.log(target)
// null
})
})
添加/删除关联关系
一对多,多对多的关系中,不但要设置关联关系,还需要添加或删除关联关系。
var Source = sequelize.define('Source', {})
, Target = sequelize.define('Target', {})
Source.hasMany(Target)
Target.belongsTo(Source)
Source.create({}).complete(function(err, source) {
Target.create({}).complete(function(err, target1) {
Target.create({}).complete(function(err, target2) {
// Set the association
source.setTargets([target1, target2]).complete(function(err) {
// Get the association
source.getTargets().complete(function(err, targets) {
console.log(targets.length) // = 2
// Remove an association
source.removeTarget(target1).complete(function(err) {
source.getTargets().complete(function(err, targets) {
console.log(targets.length) // = 1
// Check for an association
source.hasTarget(target1).complete(function(err, hasTarget) {
console.log(hasTarget) // false
// Adding an association
source.addTarget(target1).complete(function(err) {
source.getTargets().complete(function(err, targets) {
console.log(targets.length) // = 2
source.hasTarget(target1).complete(function(err, hasTarget) {
console.log(hasTarget) // true
})
})
})
})
})
})
})
})
})
})
})
综合实例
现在你已经了解了Sequelize的一些基础知识,你可能希望在一段程序中运用它们。
var Sequelize = require('sequelize')
, sequelize = new Sequelize('database_name', 'username', 'password')
, User = sequelize.define('User', {
username: Sequelize.STRING,
password: Sequelize.STRING
})
sequelize.sync({ force: true }).complete(function(err) {
User.create({ username: 'john', password: '1111' }).complete(function(err, user1) {
User.find({ username: 'john' }).complete(function(err, user2) {
console.log(user1.values, user2.values)
})
})
})
接下来,还有些什么呢?
Sequelize的其他高级特新,将在下面章节介绍:
Migrations
Data types
Configuration of the model
Validations
Finders
Associations