nodejs使用sequelize操作数据库

@youngwind 2016-03-15 21:55:05发表于 youngwind/blog Nodejs

问题

鉴于直接使用mysql包操作数据库带来的各种不方便,见 #43 ,我找到了sequelize,试用了一下,觉得还不错。

使用过程

1. 安装

npm install sequelize --save

sequelize支持如下数据库:MySQL, MariaDB, SQLite, PostgreSQL and MSSQL,不同的数据库需要安装各自的包,因为我操作的是mysql,所以要安装mysql包

npm install mysql --save

2. 创建连接

#43 说过,每次操作都需要打开和关闭连接既耗费性能,也代码冗余。mysql包本身提供方法创建连接池。

var pool  = mysql.createPool({
  connectionLimit : 10,
  host            : 'example.org',
  user            : 'bob',
  password        : 'secret'
});

传统的开发模式是:首先在主程序(如Servlet、Beans)中建立数据库连接;然后进行SQL操作,对数据库中的对象进行查 询、修改和删除等操作;最后断开数据库连接。使用这种开发模式,对于一个简单的数据库应用,由于数据库的访问不是很频繁,只需要在访问数据库时创建一个连 接,用完后就关闭它,这样做不会明显的增大系统的开销。但是对于一个复杂的数据库应用,情况就完全不同:频繁的建立、关闭数据库,会极大的降低系统的性 能,增大系统的开销,甚至成为系统的瓶颈。另外使用这种传统的模式,还必须管理数据库的每一个连接,以确保他们能正确关闭,如果出现程序异常而导致某些连 接未能关闭,将引起数据库系统中的内存泄露,最终不得不重启数据库。因此采用运行速度更快、数据库访问效率更高的数据库技术,以提高系统的运行效率将是至 关重要的。
为了解决这一问题,在JDBC2.0中提出了JDBC连接池技术,通过在客户之间共享一组连接,而不是在它们需要的时候再为它们生成,这样就可以改善资源使用,提高应用程序的响应能力。

sequelize创建连接池

// 配置写在了配置文件中
var sequelize = new Sequelize(config.mysql.database, config.mysql.user, config.mysql.password, {
  host:config.mysql.host,
  dialect:'mysql',
  pool:{
    max:5,
    min:0,
    idle:10000
  }
});

3. 定义数据结构(也就是model啦)

var User = sequelize.define('user', {
  firstName: {
    type: Sequelize.STRING,   // 定义为字符串型
    field: 'first_name'                // 这里的意思是数据库中字段为first_name,取出来的集合中的名字确实firstName
  },
  lastName: {
    type: Sequelize.STRING
  }
}, {
  freezeTableName: true   // table的名字与model的名字相同
});

4. 插入数据

User.sync({force: true}).then(function () {
  // Table created
  return User.create({
    firstName: 'John',
    lastName: 'Hancock'
  });
});

上面的代码有几个地方需要说明。

  1. sequelize采取promise模式。
  2. sync的意思是创建表,准确来说是创建model User代表的表,其中{force:true}的意思是如果之前存在这张表,则删除它。我们可以在源码中看到promise和这个参数发挥的作用。
/**
 * Sync this Model to the DB, that is create the table. Upon success, the callback will be called with the model instance (this)
 * @see {Sequelize#sync} for options
 * @return {Promise<this>}
 */
Model.prototype.sync = function(options) {
  options = options || {};
  options.hooks = options.hooks === undefined ? true : !!options.hooks;
  options = Utils._.extend({}, this.options, options);

  var self = this
    , attributes = this.tableAttributes;

  return Promise.try(function () {
    if (options.hooks) {
      return self.runHooks('beforeSync', options);
    }
  }).then(function () {
    if (options.force) {
      return self.drop(options);  // 这里啊亲!删除这张表哎呦喂!
    }
  })

我不单单想掺入数据,我还想更新,删除,各种查询怎么办?看这里

5. 存在问题

  1. 定义model的方法不通用。sequelize通过define方法定义model,但是这个定义却不能拿到其他的框架中去使用。数据结构应该是一种抽象的描述,不应该具体依赖于任何一种实现。有没有一种抽象地描述可以通用?schemas吗?
  2. 定义model和使用model的代码混在一起了。这就意味着:每次启动node项目,都会重新执行一遍model定义,难道真有这个必要吗?但是如果不执行model定义,下面的User.findOne又如何能够引用得到?