Sequelize通过数据实体映射至对象,对象映射至数据实体这种思想,将MySQL, MariaDB, SQLite or PostgreSQL这几种数据库访问方式变的更为便捷。简单而言之,就是关系对象映射(ORM)。Sequelize完全使用javascript编写,能使用于Node.js环境

入门指南

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 来自:http://my.oschina.net/zj0303/blog/305384