天天看點

【nodejs】讓nodejs像後端mvc架構(asp.net mvc)一orm篇【如EF般絲滑】typeorm介紹(8/8)前情概要使用總結typeorm 項目介紹個人的一些用法-mongodbtypeorm mongodb 初始化配置typeorm mongodb repository管理器typeorm mongodb repository 簡單封裝一些簡單的使用例子

文章目錄

前情概要

在使用nodejs開發過程中,剛好碰到需要做一個小工具,需要用到資料庫存儲功能。而我又比較懶,一個小功能不想搞一個nodejs項目,又搞一個後端項目。不如直接在nodejs裡面把對資料庫的操作也做掉。

結果百度一圈下來發現nodejs這邊還都是比較原始的、類似後端的通過coneection連資料庫,接着open,在寫sql語句幹嘛幹嘛的。經過後端這麼多年的腳手架工具熏陶,實在懶得寫這些沒營養的簡單增删改查sql語句了。

typeorm github位址

遂通過baidu、google找到了typeorm這個orm架構。果然不錯,作者自己也說大量參考了如entityframework、hibernate、dapper等等衆多orm架構。吸收了各家之所長。

更多介紹和各種示例可以參考它的demo項目,基本每個資料庫都有一個demo,然後對特性也基本都介紹到的。

比如mongodb如何映射複雜對象,關系型資料怎麼弄級聯删除之類的功能

使用總結

mysql、sqlite、mongodb3個資料庫下都使用過,使用感覺雖然沒有後端的orm那麼強大,但是在nodejs領域内,orm我覺得它已經可以說是no.1啦。當然不排除我孤陋寡聞漏了更NB的其他架構。

絕大多數的後端orm該有的功能它都有,沒有可能是沒找到正确的使用方式。為此我還發過幾條issue給開發者。基本上自己最後google找到解決方或者元件作者給與了回複。

基本功能介紹可以直接去GitHub看,基本上orm應該要有的功能它都有了。

typeorm 項目介紹

此項目github上的第一句介紹:

ORM for TypeScript and JavaScript (ES7, ES6, ES5). Supports MySQL, PostgreSQL, MariaDB, SQLite, MS SQL Server, Oracle, WebSQL databases. Works in NodeJS, Browser, Ionic, Cordova and Electron platforms.

remark:

TypeORM is highly influenced by other ORMs, such as Hibernate, Doctrine and Entity Framework.

Some TypeORM features:

  • supports both DataMapper and ActiveRecord (your choice)
  • entities and columns
  • database-specific column types
  • entity manager
  • repositories and custom repositories
  • clean object relational model
  • associations (relations)
  • eager and lazy relations
  • uni-directional, bi-directional and self-referenced relations
  • supports multiple inheritance patterns
  • cascades
  • indices
  • transactions
  • migrations and automatic migrations generation
  • connection pooling
  • replication
  • using multiple database connections
  • working with multiple databases types
  • cross-database and cross-schema queries
  • elegant-syntax, flexible and powerful QueryBuilder
  • left and inner joins
  • proper pagination for queries using joins
  • query caching
  • streaming raw results
  • logging
  • listeners and subscribers (hooks)
  • supports closure table pattern
  • schema declaration in models or separate configuration files
  • connection configuration in json / xml / yml / env formats
  • supports MySQL / MariaDB / Postgres / SQLite / Microsoft SQL Server / Oracle / sql.js
  • supports MongoDB NoSQL database
  • works in NodeJS / Browser / Ionic / Cordova / React Native / NativeScript / Expo / Electron platforms
  • TypeScript and JavaScript support
  • produced code is performant, flexible, clean and maintainable
  • follows all possible best practices
  • CLI

    And more...

個人的一些用法-mongodb

都是一些非常簡單的封裝,直接貼代碼啦。

typeorm mongodb 初始化配置

比如資料庫連結字元串,實體類,還有一些其他配置等等

InitMongoDb({
    url: _appConfig.mongodb.url,
    entities: ['bin/Entity/*.js'],
    synchronize: true,
    logging: false
});
export function InitMongoDb(dbName: string, mongoOptions: MongoConnectionOptions): void;
export function InitMongoDb(mongoOptions: MongoConnectionOptions): void;
export function InitMongoDb(): void {
    var options: MongoConnectionOptions = arguments[0];
    var dbName: any;
    if (typeof arguments[0] === 'string') {
        dbName = arguments[0];
        options = arguments[1];
    }

    var dbName = dbName || 'default';

    ManangerMongoConnection.ConnectOptions[dbName] = {
        hasGetConnection: false,
        options: options
    };
}           

typeorm mongodb repository管理器

export async function getMongoRepositoryAsync<Entity>(entityClass: ObjectType<Entity>): Promise<GDMongoRepository<Entity>>;
export async function getMongoRepositoryAsync<Entity>(entityClass: ObjectType<Entity>, dbName: string): Promise<GDMongoRepository<Entity>>
export async function getMongoRepositoryAsync<Entity>(): Promise<GDMongoRepository<Entity>> {
    var entityClass = arguments[0] as ObjectType<Entity>;
    var dbName = (arguments.length > 1 ? arguments[1] : undefined) || 'default';

    var conn = await new ManangerMongoConnection().getConnection(dbName);
    var repo = conn.getMongoRepository(entityClass);
    var gdRepo = new GDMongoRepository(repo)
    return gdRepo;
}

class ManangerMongoConnection {
    static ConnectOptions: any = {};

    async getConnection(dbName: string): Promise<Connection> {
        var conf = ManangerMongoConnection.ConnectOptions[dbName];
        if (!conf)
            throw Error(`找不到(${dbName})的資料庫配置`);
        if (conf.hasCreated)
            return conf.connection;

        var options = conf.options as MongoConnectionOptions;
        var conn = await createConnection({
            type: 'mongodb',
            url: options.url,
            synchronize: options.synchronize,
            logging: options.logging,
            entities: options.entities
        });
        conf.connection = conn;
        conf.hasCreated = true;
        return conn;
    }
}           

typeorm mongodb repository 簡單封裝

import { ObjectType, FindManyOptions, MongoRepository, ObjectLiteral, Connection, createConnection, Entity, ObjectIdColumn, Column, ObjectID, getManager } from "typeorm";
import { ObjectId } from 'mongodb'

export class GDMongoRepository<TEntity extends ObjectLiteral> {
    private _repo: MongoRepository<TEntity>;
    constructor(repo: MongoRepository<TEntity>) {
        this._repo = repo;
    }
    SaveAsync(docment: TEntity): Promise<TEntity> {
        if (!docment.createdTime) docment.createdTime = new Date();
        return this._repo.save(docment);
    }
    FindByIdAsync(id: number | string) {
        return this._repo.findOneById(new ObjectId(id));
    }

    FindByIdsAsync(ids: number[] | string[]) {
        var _id: ObjectId[] = [];
        for (let index = 0; index < ids.length; index++) {
            const element = ids[index];
            _id.push(new ObjectId(element));
        }
        return this._repo.findByIds(_id);
    }
    FindAsync(optionsOrConditions?: FindManyOptions<TEntity> | Partial<TEntity> | ObjectLiteral): Promise<TEntity[]> {
        return this._repo.find(optionsOrConditions)
    }

    CountAsync(optionsOrConditions?: FindManyOptions<TEntity> | Partial<TEntity> | ObjectLiteral): Promise<number> {
        var query: any = Object.assign({}, optionsOrConditions);
        if (query.take) delete query.take;
        if (query.skip) delete query.skip;
        if (query.order) delete query.order;
        query = query.where || query;
        return this._repo.count(query)
    }
    FindAndCount(optionsOrConditions?: FindManyOptions<TEntity> | Partial<TEntity>): Promise<[TEntity[], number]> {
        return this._repo.findAndCount(optionsOrConditions)
    }

    AggregateAsync(pipeline: ObjectLiteral[]): Promise<TEntity[]> {
        return this._repo.aggregate(pipeline).toArray()
    }
    async RemoveByIdAsync(id: number | string): Promise<number> {
        var r = await this._repo.deleteOne({ _id: new ObjectId(id) });
        if (r.deletedCount)
            return r.deletedCount
        return 0;
    }
    async RemoveAsync(conditions: ObjectLiteral): Promise<number> {
        var r = await this._repo.deleteMany(conditions);
        if (r.deletedCount)
            return r.deletedCount
        return 0;
    }

    async UpdateByIdAsync(id: number | string, update: ObjectLiteral | Partial<TEntity>): Promise<number> {
        if (update.$set || update.$unset || update.$rename) { }
        else {
            update = { $set: update }
        }
        update.$set.lastModifyTime = new Date();
        var r = await this._repo.updateOne({ _id: new ObjectId(id) }, update);
        return r.modifiedCount;
    }

    async UpdateAsync(query: FindManyOptions<TEntity> | Partial<TEntity> | ObjectLiteral, update: ObjectLiteral | Partial<TEntity>): Promise<number> {
        if (update.$set || update.$unset || update.$rename) { }
        else {
            update = { $set: update }
        }
        update.$set.lastModifyTime = new Date();
        var r = await this._repo.updateMany(query, update);
        return r.modifiedCount;
    }
}           

一些簡單的使用例子

public async list() {
        var repo = await getMongoRepositoryAsync(Host);
        var b = await repo.FindAsync();
        return b
    }

    public async info() {
        var repo = await getMongoRepositoryAsync(Host);
        var b = await repo.FindAsync({ Ip: this.request.query.ip, HostEnv: this.request.query.env });
        return b
    }           

給開源項目點贊!給國際友人點贊!