Nodejs之ORM框架

概述

寫這篇blog的緣由,想找個node的ORM框架用用,確很難找到一篇對比分析這些ORM框架的文章,惟一找到了一篇,竟然是經過star數來論英雄,我覺着很難服衆,因而就找幾個看看。後來又不想分析,由於我發現node這種野蠻生長,滋生這些ORM輪子比比皆是,遠比我想象的多;後來又覺着能夠寫,做爲一個java出身業餘研究node的就想經過java的ORM框架來洞悉node這羣ORM框架的是非曲直,因而挑了幾個框架小扯一篇。java

ORM框架

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

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的標準,可是有些語法仍是須要了解,這也或多或少增長了一些選擇難度。

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

    。。。

blog連接:dumplingbao.github.io/2019/08/29/…

相關文章
相關標籤/搜索