关于前端:Nodejs相关ORM框架分析

4次阅读

共计 5811 个字符,预计需要花费 15 分钟才能阅读完成。

概述

写这篇 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').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

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
正文完
 0