typescript+sequelize+mysql基础查询实战

6 篇文章 0 订阅
4 篇文章 0 订阅

涉及到的库:

 

 

 sequelize我们都知道它是一个orm持久层框架,所以就是基于面向对象的操作方式,本文讲解的就是入门的单表操作,sequelize在初始化的时候需要做的除了链接数据库之外,还要代理所有的实体类,在所有实体类上加上自己的crud方法,这样我们要操作时只需要导入对应的实体类即可,下面上我封装的数据库链接管理对象:

import { Options } from 'sequelize';
import { Sequelize } from 'sequelize-typescript'
import MyError from '../utils/myError';
import logger from '../utils/logger';
export class DatabaseManager {
    private static manager?: DatabaseManager = null;
    private dbInstance?: Sequelize = null;
    private dbInstanceMap?: Map<string, Sequelize> = new Map<string, Sequelize>();
    private dbConfig?: Options = null;
    private dbConfigs?: Options[] = [];
    private constructor(dbConfig: Options);
    private constructor(dbConfigs: Options[]);
    private constructor(arg: Options & Options[]) {
        if (Array.isArray(arg)) {
            this.dbConfigs = arg;
            return;
        }
        this.dbConfig = arg;
    }
    public static getInstance(dbConfig: Options & Options[]): DatabaseManager {
        if (!DatabaseManager.manager) {
            DatabaseManager.manager = new DatabaseManager(dbConfig);
        }
        return DatabaseManager.manager;
    }
    public async initDbInstance(models: string): Promise<void> {
        if (!this.dbConfig) {
            throw new MyError('db配置错误,请检查');
        }
        try {
            if (this.dbInstance) await this.dbInstance.close()
            this.dbInstance = new Sequelize(this.dbConfig);
            await this.dbInstance.authenticate();
            this.dbInstance.addModels([models]);
            await this.dbInstance.sync();
        } catch (error) {
            throw new MyError(`数据源初始化失败${error}`);
        }
    }
    public async initDbInstances(models: string[]): Promise<void> {
        if (this.dbInstanceMap.size) {
            for (const [databaseName, dbInstance] of this.dbInstanceMap.entries()) {
                await dbInstance.close();
                this.dbInstanceMap.delete(databaseName);
            }
        }
        const databases: string[] = [];
        for (let i = 0; i < this.dbConfigs.length; i++) {
            const config = this.dbConfigs[i];
            if (databases.includes(config.database)) {
                continue;
            }
            databases.push(config.database);
            try {
                const instance = new Sequelize(config);
                await instance.authenticate();
                instance.addModels([models[i]]);
                await instance.sync();
                this.dbInstanceMap.set(config.database, instance);
            } catch (error) {
                throw new MyError(`数据源初始化失败${error}`);
            }
        }
    }
    public async setDbConfig(dbConfig: Options, models: string): Promise<void> {
        this.dbConfig = dbConfig;
        await this.initDbInstance(models);
        logger.info('切换数据源成功')
    }
    public async setDbConfigs(dbConfigs: Options[], models: string[]): Promise<void> {
        this.dbConfigs = dbConfigs;
        await this.initDbInstances(models);
        logger.info('切换数据源成功')
    }
    public getDbConfig(): Options {
        return this.dbConfig;
    }
    public getDbConfigs(): Options[] {
        return this.dbConfigs;
    }
    public getDbInstance(dbName?: string): Sequelize {
        if (dbName) {
            if (!this.dbInstanceMap.size) {
                throw new MyError('请初始化数据源!')
            }
            return this.dbInstanceMap.get(dbName);
        }
        if (!this.dbInstance) {
            throw new MyError('请初始化数据源!')
        }
        return this.dbInstance;
    }
    public getAllDbInstance(): Map<string, Sequelize> {
        if (!this.dbInstanceMap.size) {
            throw new MyError('请先初始化数据源!')
        }
        return this.dbInstanceMap;
    }
    public close(dbName?: string): void {
        if (dbName) {
            this.dbInstanceMap.get(dbName) && this.dbInstanceMap.get(dbName).close();
            return;
        }
        this.dbInstance && this.dbInstance.close()
    }
}
export default DatabaseManager;

这里做了个封装,可以接收多个db数据源,也可以初始化后切换单个/多个数据源,其中核心部分无非就是给实体类绑定链接好的数据库操作对象,让实体类映射到对应的表

实体类的装饰器写法:

// more annotations see https://www.npmjs.com/package/sequelize-typescript
import { Table, Column, Model, AllowNull, AutoIncrement, PrimaryKey, Comment, Unique, CreatedAt, UpdatedAt, DeletedAt, DataType, NotEmpty } from 'sequelize-typescript'
import { Optional } from 'sequelize';
import { swaggerClass, swaggerProperty } from 'koa-swagger-decorator';
export interface MyInfoAttributes {
    id?: number;
    createdAt?: Date;
    updatedAt?: Date;
    deletionDate?: Date;
    uName?: string;
    qq?: string;
    githubUrl?: string;
    content?: string;
}
export interface MyInfoCreationAttributes extends Optional<MyInfoAttributes, 'id'> { }
@swaggerClass()
@Table({
    tableName: 'myinfo'
})
export default class MyInfo extends Model<MyInfoAttributes, MyInfoCreationAttributes> {

    @swaggerProperty({
        type: 'number',
        required: false
    })
    @Comment('主键id')
    @AllowNull(false)
    @NotEmpty
    @AutoIncrement
    @PrimaryKey
    @Column({
        type: DataType.INTEGER
    })
    id?: number;

    @swaggerProperty({
        type: 'object',
        required: false
    })
    @Comment('创建时间')
    @CreatedAt
    @Column({
        type: DataType.DATE
    })
    createdAt?: Date;

    @swaggerProperty({
        type: 'object',
        required: false
    })
    @Comment('更新时间')
    @UpdatedAt
    @Column({
        type: DataType.DATE
    })
    updatedAt?: Date;

    @swaggerProperty({
        type: 'object',
        required: false
    })
    @Comment('删除时间')
    @DeletedAt
    @Column({
        type: DataType.DATE
    })
    deletionDate?: Date;

    @swaggerProperty({
        type: 'string',
        required: true
    })

    @Comment('博主名字')
    @Column({
        type: DataType.STRING
    })
    uName?: string;

    @swaggerProperty({
        type: 'string',
        required: false
    })
    @Comment('博主qq')
    @Column({
        type: DataType.STRING
    })
    qq?: string;

    @swaggerProperty({
        type: 'string',
        required: false
    })
    @Comment('博主github地址')
    @Column({
        type: DataType.STRING
    })
    githubUrl?: string;

    @swaggerProperty({
        type: 'string',
        required: false
    })
    @Comment('博主个人描述')
    @Column({
        type: DataType.STRING
    })
    content?: string;
}

通过注解的形式标明字段的特性,比如主键自动增长,字段类型,字段备注啥的信息,更多的注解还请查看sequelize-typescript官方文档,swaggerProperty不是sequelize的注解,是swagger接口用来标注入参类型啥的校验信息的

如何使用实体类操作数据库?这里封装了一个baseDao,所有的dao都可以继承从而得到curd基础方法:

export default class BaseDao {
    private Entity: any;
    public constructor(Entity: any) {
        this.Entity = Entity;
    }
    public async findAll(): Promise<Array<any>> {
        return await this.Entity.findAll()
    }
    public async findById(id: number): Promise<any> {
        return await this.Entity.findByPk(id)
    }
    public async updateById(entity: any): Promise<number> {
        const [affectRowCount] = await this.Entity.update(
            entity.toJSON(),
            {
                where: {
                    id: entity.id
                }
            }
        );
        return affectRowCount;
    }
    public async insert(entity: any): Promise<any> {
        const newRecord = await entity.save()
        return newRecord;
    }
    public async deleteById(id: number): Promise<any> {
        const record = await this.Entity.findByPk(id)
        return await record.destroy();
    }
}

可以看到其实本质就是调用实体类Entity身上的sequelize的方法进行操作,至于多表关联,级联等操作就要看文档进行实体类之间的关系映射和绑定了,这里不做赘述,事务回滚操作官方文档也有,可自行查询或者留言up一起讨论.

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值