写这篇blog的缘由,想找个node的ORM框架用用,确很难找到一篇对比分析这些ORM框架的文章,惟一找到了一篇,竟然是经过star数来论英雄,我觉着很难服众,因而就找几个看看。后来又不想分析,由于我发现node这种野蛮生长,滋生这些ORM轮子比比皆是,远比我想象的多;后来又觉着能够写,做为一个java出身业余研究node的就想经过java的ORM框架来洞悉node这群ORM框架的是非曲直,因而挑了几个框架小扯一篇。java
ORM框架:Object Relational Mapping,对象-关系-映射,因此说ORM框架就是用面向对象的方式和目前的关系型数据库作匹配,java开发者目前主流的hibernate、mybatis很熟悉了,JDBC原始驱动的方式想必也不在成为主流了。下面介绍几款node的ORM框架,介绍以前先介绍ORM的两种模式:node
Active Record 模式:活动记录模式,领域模型模式一个模型类对应关系型数据库中的一个表,模型类的一个实例对应表中的一行记录。这个不难理解,比较简单,可是不够灵活,再看另外一种模式,比较一下mysql
Data Mapper 模式:数据映射模式,领域模型对象和数据表是松耦合关系,只进行业务逻辑的处理,和数据层解耦。须要一个实体管理器来将模型和持久化层作对应,这样一来,灵活性就高,固然复杂性也增长了。git
因此说,Data Mapper模式对业务代码干预少,Active Record模式直接在对象上CRUD,代码编写也更方便,这就像hibernate和mybatis两种框架,若是想深刻研究,能够了解一下贫血与充血领域对象的平衡。es6
有这么一句话很认同,ActiveRecord更加适合快速开发成型的短时间简单项目,而DataMapper更加适合长线开发,保持业务逻辑与数据存储独立的复杂项目。除此以外,技术选型还要考虑其余因素,好比项目历史背景等等。github
TypeORM 是一个 ORM 框架,详细介绍见 TypeORM 官方介绍,TypeORM 也借鉴了hibernate,因此你会发现它特别熟悉,尤为是装饰类的方式。sql
闲话少说,直接用CLI 命令快速构建项目数据库
npm install typeorm -g
复制代码
建立项目express
typeorm init --name MyProject --database mysql
复制代码
name
是项目的名称,database
是将使用的数据库,TypeORM 支持多种数据库。npm
生成文档结构
MyProject
├── src // TypeScript 代码
│ ├── entity // 存储实体(数据库模型)的位置
│ │ └── User.ts // 示例 entity
│ ├── migration // 存储迁移的目录
│ └── index.ts // 程序执行主文件
├── .gitignore // gitignore文件
├── ormconfig.json // ORM和数据库链接配置
├── package.json // node module 依赖
├── README.md // 简单的 readme 文件
└── tsconfig.json // TypeScript 编译选项
复制代码
修改 ormconfig.json
数据库配置文件,直接运行就能够了
npm start
复制代码
看一下实体model,user类
import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
firstName: string;
@Column()
lastName: string;
@Column()
age: number;
}
复制代码
CRUD操做:逻辑层
import "reflect-metadata";
import {createConnection} from "typeorm";
import {User} from "./entity/User";
createConnection().then(async connection => {
console.log("Inserting a new user into the database...");
const user = new User();
user.firstName = "Timber";
user.lastName = "Saw";
user.age = 25;
await connection.manager.save(user);
console.log("Saved a new user with id: " + user.id);
console.log("Loading users from the database...");
const users = await connection.manager.find(User);
console.log("Loaded users: ", users);
console.log("Here you can setup and run express/koa/any other framework.");
}).catch(error => console.log(error));
复制代码
因此,TypeORM的方式很像hibernate的方式,虽然es6中就已经有装饰器相似java的注解的功能了,可是仍是和装饰器有所区别,由于TypeORM采用的是TypeScript 的方式,TypeScript 是 JavaScript 的一个超集,TypeScript 采用类型注解方式,虽然支持es6的标准,可是有些语法仍是须要了解,这也或多或少增长了一些选择难度。
这个被star数最多了一个ORM框架,官方竟然不给中文文档,找个CLI命令快速构建也没有,也没找到个合适轮子,只能本身搭了,也不是少了轮子就不能活了。不过Sequelize的官网文档看着很顺眼,不得不称赞一下,须要注意的一点Sequelize v5版本发生了比较大的变化,这里我以最新版本v5版本为主,老版本能够本身看看下官方文档。Sequelize v5
安装npm包
$ npm install --save sequelize
$ npm install --save mysql2
复制代码
数据库的配置文件config.js
module.exports = {
database: {
dbName: 'TEST',
host: 'localhost',
port: 3306,
user: 'root',
password: '123456'
}
}
复制代码
构建数据库访问公共文件db.js
const Sequelize = require('sequelize')
const {
dbName,
host,
port,
user,
password
} = require('../config').database
const sequelize = new Sequelize(dbName, user, password, {
dialect: 'mysql',
host,
port,
logging: true,
timezone: '+08:00',
define: {
// create_time && update_time
timestamps: true,
// delete_time
paranoid: true,
createdAt: 'created_at',
updatedAt: 'updated_at',
deletedAt: 'deleted_at',
// 把驼峰命名转换为下划线
underscored: true,
scopes: {
bh: {
attributes: {
exclude: ['password', 'updated_at', 'deleted_at', 'created_at']
}
},
iv: {
attributes: {
exclude: ['content', 'password', 'updated_at', 'deleted_at']
}
}
}
}
})
// 建立模型
sequelize.sync({
force: false
})
module.exports = {
sequelize
}
复制代码
model
const {Sequelize, Model} = require('sequelize')
const {db} = require('../../db')
class User extends Model {}
User.init({
// attributes
firstName: {
type: Sequelize.STRING,
allowNull: false
},
lastName: {
type: Sequelize.STRING
// allowNull defaults to true
}
}, {
db,
modelName: 'user'
// options
});
复制代码
还有一种写法,兼容老版本,不推荐
const User = db.define('user', {
// attributes
firstName: {
type: Sequelize.STRING,
allowNull: false
},
lastName: {
type: Sequelize.STRING
// allowNull defaults to true
}
}, {
// options
});
复制代码
这种其实是sequelize.define内部调用了model.init,可是老版本是没有第一种写法的。
此外须要知道的是,sequelize还默认为每一个模型定义字段id(主键)、createdat和updatedat,也能够进行设置。
咱们的db.js文件里面配置了,不自动建立模型,也就是自动建立数据表,关闭是有缘由的,由于若是表存在会先drop而后再建立,这种操做自己就很可怕的
// 建立模型
sequelize.sync({
force: false
})
复制代码
单个模型也能够配置,切记这种操做很危险,尤为是生成环境
// Note: using `force: true` will drop the table if it already exists
User.sync({ force: true }).then(() => {
// Now the `users` table in the database corresponds to the model definition
return User.create({
firstName: 'John',
lastName: 'Hancock'
});
});
复制代码
CRUD操做:而后看一下逻辑层,就很是简单了,直接使用ES7 async/await
便可
// Find all users
User.findAll().then(users => {
console.log("All users:", JSON.stringify(users, null, 4));
});
// Create a new user
User.create({ firstName: "Jane", lastName: "Doe" }).then(jane => {
console.log("Jane's auto-generated ID:", jane.id);
});
// Delete everyone named "Jane"
User.destroy({
where: {
firstName: "Jane"
}
}).then(() => {
console.log("Done");
});
// Change everyone without a last name to "Doe"
User.update({ lastName: "Doe" }, {
where: {
lastName: null
}
}).then(() => {
console.log("Done");
});
复制代码
由此来看,没有typeorm装饰类的方式看着顺眼,可是总体构造也容易上手,操做简单,容易理解,看官网文档,功能覆盖强大,typeorm用户反馈使用问题比Sequelize要多,后期用到再作比较。
ORM2貌似没有正了八经的官网,因此看起来就特别麻烦,可是能够看一下github介绍node-orm2,只支持四种数据库MySQL、PostgreSQL、Amazon Redshift、SQLite,这个我没写demo,直接分析一下
安装
npm install orm
复制代码
数据库链接
var orm = require("orm");
orm.connect("mysql://username:password@host/database",
function (err, db) {
// ...里面一些参数不详细写了
});
复制代码
model
var Person = db.define('person', {
name: String,
surname: String,
age: String,
male: boolean
}, {
identityCache : true
});
复制代码
CRUD操做
Person.create([
{
name: "John",
surname: "Doe",
age: 25,
male: true
},
{
name: "Liza",
surname: "Kollan",
age: 19,
male: false
}
], function (err, items) {
// err - description of the error or null
// items - array of inserted items
});
复制代码
Person.get(1, function (err, John) {
John.name = "Joe";
John.surname = "Doe";
John.save(function (err) {
console.log("saved!");
});//保存
Person.find({ surname: "Doe" }).remove(function (err) {
// Does gone..
});//删除
});
复制代码
Person.find({
name: "admin"})
.limit(3)
.offset(2)//跳过
.only("name", "age")//返回字段
.run(function(err, data) {
});
复制代码
因此,准确应该是node-orm2,写法和sequelize相似,可是文档确实不行,数据库支持也少,很难想象后续的可维护性。
bookshelf(这个用的也挺多)
persistencejs
waterline
mongoose
node-mysql
knex
。。。