概述
写这篇blog的起因,想找个node的ORM框架用用,确很难找到一篇比照剖析这些ORM框架的文章,惟一找到了一篇,竟然是通过star数来论英雄,我觉着很难服众,于是就找几个看看。起初又不想剖析,因为我发现node这种横蛮成长,滋生这些ORM轮子亘古未有,远比我设想的多;起初又觉着能够写,作为一个java出身业余钻研node的就想通过java的ORM框架来洞悉node这群ORM框架的是非曲直,于是挑了几个框架小扯一篇。
ORM框架
ORM框架:Object Relational Mapping,对象-关系-映射,所以说ORM框架就是用面向对象的形式和目前的关系型数据库做匹配,java开发者目前支流的hibernate、mybatis很相熟了,JDBC原始驱动的形式想必也不在成为支流了。上面介绍几款node的ORM框架,介绍之前先介绍ORM的两种模式:
Active Record 模式:流动记录模式,畛域模型模式一个模型类对应关系型数据库中的一个表,模型类的一个实例对应表中的一行记录。这个不难理解,比较简单,然而不够灵便,再看另一种模式,比拟一下
Data Mapper 模式:数据映射模式,畛域模型对象和数据表是松耦合关系,只进行业务逻辑的解决,和数据层解耦。须要一个实体管理器来将模型和长久化层做对应,这样一来,灵活性就高,当然复杂性也减少了。
所以说,Data Mapper模式对业务代码干涉少,Active Record模式间接在对象上CRUD,代码编写也更不便,这就像hibernate和mybatis两种框架,如果想深入研究,能够理解一下
有这么一句话很认同,ActiveRecord更加适宜疾速开发成型的短期简略我的项目,而DataMapper更加适宜长线开发,放弃业务逻辑与数据存储独立的简单我的项目。除此之外,技术选型还要思考其余因素,比方我的项目历史背景等等。
TypeORM
TypeORM 是一个 ORM 框架,具体介绍见 TypeORM 官网介绍,TypeORM 也借鉴了hibernate,所以你会发现它特地相熟,尤其是装璜类的形式。
闲话少说,间接用CLI 命令疾速构建我的项目
npm install typeorm -g
创立我的项目
typeorm init --name MyProject --database mysql
name
是我的项目的名称,database
是将应用的数据库,TypeORM 反对多种数据库。
生成文档构造
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的规范,然而有些语法还是须要理解,这也或多或少减少了一些抉择难度。
Sequelize
这个被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').databaseconst 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而后再创立,这种操作自身就很可怕的
参考nodejs进阶视频解说:进入学习
// 创立模型sequelize.sync({ force: false})
单个模型也能够配置,切记这种操作很危险,尤其是生成环境
// Note: using `force: true` will drop the table if it already existsUser.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 usersUser.findAll().then(users => { console.log("All users:", JSON.stringify(users, null, 4));});// Create a new userUser.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
ORM2貌似没有正了八经的官网,所以看起来就特地麻烦,然而能够看一下github介绍node-orm2,只反对四种数据库MySQL、PostgreSQL、Amazon Redshift、SQLite,这个我没写demo,间接剖析一下
装置
npm install orm
数据库连贯
var orm = require("orm");orm.connect("mysql://username:[email protected]/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