Open
Description
问题
鉴于直接使用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'
});
});
上面的代码有几个地方需要说明。
- sequelize采取promise模式。
- 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. 存在问题
- 定义model的方法不通用。sequelize通过define方法定义model,但是这个定义却不能拿到其他的框架中去使用。数据结构应该是一种抽象的描述,不应该具体依赖于任何一种实现。有没有一种抽象地描述可以通用?schemas吗?
- 定义model和使用model的代码混在一起了。这就意味着:每次启动node项目,都会重新执行一遍model定义,难道真有这个必要吗?但是如果不执行model定义,下面的User.findOne又如何能够引用得到?