KOA2 + MongoDB 和 MySQL混用的项目 nodejs restful API框架

938 阅读6分钟

有时候因项目需要.在koa中需要使用多个数据库和多种数据库

此以 MongoDB 和 MySQL为例

此项目中用到了2个MySQL 和 多个MongoDB,其中MongoDB的库名生成是由时间生成的如2018_11_09,这种采用动态库名链接的方式进行连接.

github地址: github.com/langyuxians… 

可以与配套的管理后台一起使用 github.com/langyuxians…

如果对你有帮助的话,欢迎star,有问题请在此留言

也可以在github Issues提问 或者直接 联系作者 109643291@qq.com

欢迎加入作者所在的QQ群: 46153838

作者个人网站: www.hao2013.cn

CSDN: blog.csdn.net/qq_33270001

首先创建一个全局的配置 config.js配置如下:

import path from 'path';
 
// 系统配置
export const System = {
    API_server_type: 'http://', // API服务器协议类型,包含"http://""https://"
    API_server_host: 'localhost', // API服务器暴露的域名地址,请勿添加"http://"
    API_server_port: '3000', // API服务器监听的端口号
    HTTP_server_type: 'http://', // HTTP服务器协议类型,包含"http://""https://"
    HTTP_server_host: 'www.haoal.cn', // HTTP服务器地址,请勿添加"http://" (即前端调用使用的服务器地址,如果是APP请设置为 * )
    HTTP_server_port: '65534', // HTTP服务器端口号
    System_country: 'zh-cn', // 所在国家的国家代码
    System_plugin_path: path.join(__dirname, './plugins'), // 插件路径
    Session_Key: 'RESTfulAPI', // 生产环境务必随机设置一个值
};
 
//数据库配置
export const DB = {
    relationalConfs: [{
            DB_type: 'mysql', // 数据库类型
            dbName: 'db1', //命名为唯一 调用的时候
            host: '192.168.0.1', // 服务器地址
            port: 3306, // 数据库端口号
            username: 'test', // 数据库用户名
            password: 'test', // 数据库密码
            database: 'db1', // 数据库名称
            //prefix: 'api_', // 默认"api_"
            dialectOptions: { // MySQL > 5.5,其它数据库删除此项
                charset: 'utf8mb4',
                //collate: 'utf8mb4_unicode_520_ci',
                supportBigNumbers: true,
                bigNumberStrings: true,
                //requestTimeout: 60 * 1000 //设置连接超时时间
            },
            pool: {
                max: 50, // 连接池中最大连接数量
                min: 0, // 连接池中最小连接数量
                idle: 10000 // 如果一个线程 10 秒钟内没有被使用过的话,那么就释放线程
            }
        },
        
        {
            DB_type: 'mysql', // 数据库类型
            dbName: 'db2', //命名为唯一 调用的时候
            host: '192.168.0.1', // 服务器地址
            port: 3306, // 数据库端口号
            username: 'test', // 数据库用户名
            password: 'test', // 数据库密码
            database: 'db2', // 数据库名称
            dialectOptions: { // MySQL > 5.5,其它数据库删除此项
                charset: 'utf8mb4',
                supportBigNumbers: true,
                bigNumberStrings: true,
            },
            pool: {
                max: 50, // 连接池中最大连接数量
                min: 0, // 连接池中最小连接数量
                idle: 10000 // 如果一个线程 10 秒钟内没有被使用过的话,那么就释放线程
            }
        }
    ],
    mongoConf: {
        host: 'mongodb://localhost', // 服务器地址
        port: 27017, // 数据库端口号
        username: '', // 数据库用户名
        password: '', // 数据库密码
        database: 'tx', // 数据库名称
        prefix: 'api_' // 默认"api_"
    }
};

 MongoDB 的操作使用 mongodb 模块

需要安装 mongodb npm i mongodb --save

mongodb 的文档在这里, 貌似只有英文版本的 飞机票如下: https: //docs.mongodb.com/manual/reference/method/

新建一个MongoDB工具类 mongoUtil.js 内容如下:

/**
 * mongoDB工具类
 * 封装mongoDB的增删改查方法
 * https: //docs.mongodb.com/manual/reference/method/
 */
import {
    DB
} from '../config';
const assert = require('assert');
 
//引入mongoDB组件
const MongoClient = require('mongodb').MongoClient;
//引入mongoDB操作_id的函数
const objectID = require('mongodb').ObjectId;
 
//将所有的方法封装到类里
class MongoDBTool {
    constructor() {
        this.objectID = objectID;
    }
 
    /**
     * 链接数据库与关闭数据库的方法
     * 参照这个格式: mongoose.connect('mongodb://user:password@127.0.0.1:27017/dbname'), 其中dbname是必选项, 不写会报错。 user和password可选。
     * @param {*} callback
     * @param {*} dbName 库名 不传则使用默认配置
     */
    connect(callback, dbName) {
        MongoClient.connect(DB.mongoConf.host, {
            useNewUrlParser: true //
        }, (err, client) => {
            assert.strictEqual(null, err);
            console.log(`${DB.mongoConf.host} 数据库连接成功!!!`);
            //拿到数据库
            const db = client.db(dbName || DB.mongoConf.database);
            //操作数据
            callback(err, db);
            //关闭数据库
            client.close();
        });
    }
 
    /**
     * 增
     * @param {* string} table  表名
     * @param {* arr or obj} data  数据
     * @param {*} dbName 库名
     * @return 结果
     */
    insert({
        table,
        data,
        dbName
    }) {
        if (typeof table != 'string') throw new Error('请检查传入的参数是否正确');
        return new Promise((resolve, reject) => {
            this.connect(async(err, db) => {
                if (err) reject(err);
                //取到想要的表
                const collection = db.collection(table);
                if (Array.isArray(data)) { //判断数据是否是数组
                    //插入多条数据
                    const result = await collection.insertMany(data);
                    console.log(`插入${result.n}条数据`, result);
                    resolve(result.n);
                } else {
                    //插入一条数据
                    const result = await collection.insertOne(data);
                    console.log(`插入${result.n}条数据`, result);
                    resolve(result.n);
                }
            }, dbName);
        });
    }
 
    /**
     * 删除一条
     * @param {* string} table 集合名
     * @param {* obj} filters 删除的条件
     * @param {*} dbName 库名
     * @return {* function} 返回结果
     */
    deleteOne({
        table,
        filters,
        dbName
    }) {
        if (typeof table != 'string') throw new Error('请检查传入的参数是否正确');
        return new Promise((resolve, reject) => {
            this.connect(async(err, db) => {
                if (err) reject(err);
                const collection = db.collection(table);
                const result = await collection.deleteOne(filters);
                console.log(`删除${result.n}条数据`, result);
                resolve(result.n);
            }, dbName);
        });
    }
 
    /**
     * 删除多条
     * @param {* string} table 集合名
     * @param {* obj} filters 删除的条件
     * @param {*} dbName 库名
     * @return {*} 返回结果
     */
    deleteMany({
        table,
        filters,
        dbName
    }) {
        if (typeof table != 'string') throw new Error('请检查传入的参数是否正确');
        return new Promise((resolve, reject) => {
            this.connect(async(err, db) => {
                if (err) reject(err);
                const collection = db.collection(table);
                const result = await collection.deleteMany(filters);
                console.log(`删除${result.n}条数据`, result);
                resolve(result.n);
            }, dbName);
        });
    }
 
    /**
     * 修改一条
     * @param {* string} table  集合名
     * @param {* obj} filters 更新的条件
     * @param {* obj} data  更新数据
     * @param {*} dbName 库名
     * @return { Number} 返回结果
     */
    upadteOne({
        table,
        filters,
        data,
        dbName
    }) {
        if (typeof table != 'string' && arguments.length === 3) throw new Error('请检查传入的参数是否正确');
        return new Promise((resolve, reject) => {
            this.connect(async(err, db) => {
                if (err) reject(err);
                const collection = db.collection(table);
                const result = await collection.updateOne(filters, {
                    $set: data
                });
                console.log(`修改${result.n}条数据`, result);
                resolve(result.n);
            }, dbName);
        });
    }
 
    /**
     * 改多条
     * @param {* string} table  集合名
     * @param {* obj} filters 更新的条件
     * @param {* obj} data  更新数据
     * @param {*} dbName 库名
     * @return { Number} 返回结果
     */
    updateMany({
        table,
        filters,
        data,
        dbName
    }) {
        if (typeof table != 'string' && arguments.length === 3) throw new Error('请检查传入的参数是否正确');
        return new Promise((resolve, reject) => {
            this.connect((err, db) => {
                if (err) reject(err);
                const collection = db.collection(table);
                collection.updateMany(filters, {
                    $set: data
                }).then(({
                    result
                }) => {
                    console.log(`修改${result.n}条数据`, result);
                    resolve(result.n);
                });
            }, dbName);
        });
    }
 
    /**
     * 查询数据
     * @param {* string} table  表名
     * @param {* obj} filters  条件
     * @param {*} attributes 输出指定列
     * @param {*} dbName 库名
     * @return {* Array} 返回结果集列表
     */
    findAll({
        table,
        filters,
        attributes,
        dbName
    }) {
        if (typeof table != 'string') throw new Error('请检查传入的参数是否正确');
        return new Promise((resolve, reject) => {
            this.connect((err, db) => {
                if (err) reject(err);
                const collection = db.collection(table);
                collection.find(filters, {
                    projection: attributes
                }).toArray((err, result) => {
                    assert.strictEqual(err, null);
                    console.log(`查询数据${result.length}条数据`, result);
                    resolve(result);
                });
            }, dbName);
        });
    }
 
    /**
     * 查询数据
     * @param {*} collectionName
     * @param {*} filters
     * @param {*} attributes 输出指定列
     * @param {*} database 库名
     * @return {Object} 返回结果对象
     */
    findOne({
        table,
        filters,
        attributes,
        dbName
    }) {
        if (typeof table != 'string') throw new Error('请检查传入的参数是否正确');
        return new Promise((resolve, reject) => {
            this.connect(async(err, db) => {
                if (err) reject(err);
                const collection = db.collection(table);
                const result = await collection.findOne(filters, {
                    projection: attributes
                });
                assert.strictEqual(err, null);
                console.log(`查询数据`, result);
                resolve(result);
            }, dbName);
        });
    }
 
    /**
     * 获取总条数
     * @param {*} collectionName
     * @param {*} database 库名
     * @return {* Number} 返回数量
     */
    getAllCount({
        table,
        filters,
        dbName
    }) {
        if (typeof table != 'string') throw new Error('请检查传入的参数是否正确');
        return new Promise((resolve, reject) => {
            this.connect(async(err, db) => {
                if (err) reject(err);
                //取到想要的表
                const collection = db.collection(table);
                const result = await collection.count(filters);
                console.log(`查询数据${result}条数据`, result);
                resolve(result);
            }, dbName);
        });
    }
 
    /**
     * 分页查询数据
     * @param {* string} table  表名
     * @param {* obj} filters  条件
     * @param {*} dbName 库名
     * @param {*} attributes 输出指定列
     * @param {*} page 分页参数 当前索引
     * @param {*} limit 每页大小
     * @return {* Array} 返回结果集列表
     */
    findAndCount({
        table,
        filters,
        attributes,
        dbName,
        page,
        limit
    }) {
        if (typeof table != 'string') throw new Error('请检查传入的参数是否正确');
        return new Promise((resolve, reject) => {
            this.connect(async(err, db) => {
                if (err) reject(err);
                const collection = db.collection(table);
                let queryData = {
                        projection: attributes
                    }
                    //分页查询
                if (page && limit) {
                    queryData.skip = Number((page - 1) * limit);
                    queryData.limit = Number(limit);
                }
                collection.find(filters, queryData).toArray((err, result) => {
                    assert.strictEqual(err, null);
                    console.log(`分页查询数据${result.length}条数据`, result);
                    resolve(result);
                });
            }, dbName);
        });
    }
 
}
 
//导出对象
export default new MongoDBTool();

MySQL的操作 使用 sequelize.js 模块,这基本上是傻瓜式的操作方式了.

sequelize 需要安装 npm i sequelize --save

这里是 sequelize 的中文文档 飞机票: itbilu.com/nodejs/npm/…

因为要导出 Sequelize 和 Sequelize的实例,便用了Object.assign() 方法,可能有疑问,为啥不用 es6 展开运算符(...),我用过了,当时有个莫名其妙的bug.......

新建一个sequelize.js 的文件 内容如下:

/**
 * Sequelize.js api说明文档
 * https: //itbilu.com/nodejs/npm/V1PExztfb.html
 */
import Sequelize from 'sequelize';
import {
    DB
} from '../config';
 
/**
 * 挂载多个mysql
 */
let mysqls = {};
DB.relationalConfs.forEach(item => {
    if (!mysqls[`${item.dbName}Util`]) {
        // console.log(database);
        mysqls[`${item.dbName}Util`] = new Sequelize(item.database, item.username, item.password, {
            host: item.host, // 数据库地址
            dialect: item.DB_type, // 指定连接的数据库类型
            dialectOptions: item.dialectOptions, //mysql专用
            pool: item.pool //连接池对象
        });
        mysqls[`${item.dbName}Util`].authenticate().then(() => {
            console.log(`${item.dbName} 连接成功!`);
        }).catch(err => {
            console.error(`${item.dbName} 连接出错`, err);
        });
    }
});
 
//配置关系型数据库ORM
export default Object.assign(Sequelize, mysqls);

然后列举一下MongoDB的使用方法:

假设有个Service类,如下 TestService.js

import result from '../tools/Result';
import mongoUtil from '../lib/mongoUtil';
import {
    testModel
} from '../models';
 
/**
 * test TestService
 * 本页面处理业务逻辑 接收参数与返回处理结果
 */
class TestService {
 
    /**
     * get
     * @param {*} ctx
     */
    async getTest({
        date
    }) {
        try {
            const res = await mongoUtil.findAll('user', null, '2018-11-05');
            return result.pageData(null, null, res, res.length, 10, 1);
        } catch (error) {
            console.log(error);
            return result.failed();
        }
    }
 
    /**
     * post
     * @param {*} ctx
     */
    async postTest(data) {
        try {
            const res = await mongoUtil.insert('user', data, '2018-11-06');
            if (res > 0) {
                return result.success();
            } else {
                return result.failed();
            }
        } catch (error) {
            console.log(error);
            return result.failed(error.toString());
        }
    }
 
    /**
     * put
     * @param {*} ctx
     */
    async putTest(id, data) {
        try {
            const res = await mongoUtil.upadteOne('user', {
                _id: mongoUtil.objectID(id)
            }, data);
            if (res > 0) {
                return result.success();
            } else {
                return result.failed(`修改失败!`);
            }
        } catch (error) {
            console.log(error);
            return result.failed(error.toString());
        }
    }
 
    /**
     * delete
     */
    async deleteTest(id) {
        try {
            const res = await mongoUtil.deleteOne('user', {
                _id: mongoUtil.objectID(id)
            });
            if (res > 0) {
                return result.success();
            } else {
                return result.failed(`删除失败!`);
            }
        } catch (error) {
            console.log(error);
            return result.failed(error.toString());
        }
    }
}
 
module.exports = new TestService();

下面是sequelize.js 的使用方法

首先新建一个数据模型 UsersModel.js 内容如下:

/**
 * 测试表数据模型
 * @param {*} sequelize
 * @param {*} DataTypes
 * 此模型仅限关系型数据库使用
 */
export default (sequelize, DataTypes) => {
    return sequelize.define('users', {
        id: {
            type: DataTypes.INTEGER(11),
            allowNull: false,
            primaryKey: true,
            autoIncrement: true
        },
        username: {
            type: DataTypes.STRING(32),
            allowNull: false
        },
        password: {
            type: DataTypes.STRING(32),
            allowNull: false
        },
        createdAt: {
            type: DataTypes.INTEGER(32),
            allowNull: false,
            defaultValue: Date.parse(new Date())
        },
        updatedAt: {
            type: DataTypes.INTEGER(32),
            allowNull: false,
            defaultValue: Date.parse(new Date())
        }
    }, {
        tableName: 'users'
    });
};

接下来新建一个 UserService.js 类 如下:

import result from '../tools/Result';
import sequelize from '../lib/sequelize';
const {
    database1Util
} = sequelize;
const userModel = database1Util.import(`../models/userModel`);
 
/**
 * test TestService
 * 本页面处理业务逻辑 接收参数与返回处理结果
 */
module.exports = class UserService {
 
    /**
     * 用户注册
     * @param {*} user
     */
    async userRegister(user) {
        try {
            const res = await userModel.create(user);
            return result.success(null, res);
        } catch (error) {
            console.log(error);
            return result.failed();
        }
    }
 
    /**
     * 用户登录
     * @param {*} user
     */
    async userLogin({
        username,
        password
    }) {
        try {
             const res = await userModel.findOne({
                 where: {
                     username,
                     password
                 }
             });
             if (res) {
                //res要生成jwt的编码串这里就不详细细解释了
                 return result.success('签发token', res);
             } else {
                 return result.failed(`用户名或密码错误`);
             }
          
        } catch (error) {
            console.log(error);
            return result.failed();
        }
    }
 
    /**
     * 获取用户列表
     * @param {*} ctx
     */
    async getUserList({
        authorization
    }) {
        try {
            const res = await userModel.findAll({
                where: {},
                attributes: ['id', 'username', 'password']
            });
            return result.pageData(null, null, res, res.length, 10, 1);
        } catch (error) {
            console.log(error);
            return result.failed();
        }
    }
 
    /**
     * 事务demo
     * @param {*} data
     */
    async demoTest({userName}) {
        // 创建事务
        database1Util.transaction((t) => {
            // 在事务中执行操作
            return userModel.create({
                userName
            }, { transaction: t }).then((user) => {
                return AgentIpListModel.findAndCount(user, { transaction: t })
            });
        }).then((results) => {
            console.log(`操作成功,事务会自动提交`, results);
            /* 操作成功,事务会自动提交 */
        }).catch((err) => {
            console.log(`操作失败,事件会自动回滚`, err);
            /* 操作失败,事件会自动回滚 */
        });
    }
 
    /**
     * 事务demo
     * @param {*} data
     */
    async demoTest1(data) {
        try {
            // 创建事务
            /* 操作成功,事务会自动提交 */
            /* 操作失败,事件会自动回滚 */
            const results = await database1Util.transaction(async(t) => {
                // 在事务中执行操作
                const a = await a.create( /* {} */ , { transaction: t });
                const b = await b.create( /* {} */ , { transaction: t });
                const c = await c.create( /* {} */ , { transaction: t });
                return c;
            });
            return result.success();
        } catch (error) {
            return result.failed();
        }
    }
};

最后再分享一个 restful API的返回类 Result.js 统一数据返回的格式

/**
 * 返回数据实体对象
 */
class Result {
 
    constructor() {
        this.CODE = {
            SUCCESS: 200, //成功
            OTHER: 204, //其它状态
            FAILED: 400, //操作失败
            AUTHORITIES: 401, //身份验证失败
            NO_AUTHORITY: 403 //无权限
        };
 
        //返回提示
        this.MESSAGE = {
            SUCCESS: `SUCCESS`,
            FAILED: `操作失败!`,
            PARAMS_LACK: `参数不齐!`,
            AUTHORITIES: `登陆失效或身份过期!` //身份验证失败
        };
    }
 
    /**
     * 返回成功结果
     */
    success(msg, data) {
        return {
            code: this.CODE.SUCCESS,
            data,
            msg: msg || this.MESSAGE.SUCCESS
        };
    }
 
    /**
     * 请求操作失败
     */
    failed(msg, code, data) {
        return {
            code: code || this.CODE.FAILED,
            data,
            msg: msg || this.MESSAGE.FAILED
        };
    }
 
    /**
     * 参数不齐
     * @param {*} msg
     * @param {*} code
     * @param {*} data
     */
    paramsLack(msg, code, data) {
        return {
            code: code || this.CODE.FAILED,
            data,
            msg: msg || this.MESSAGE.PARAMS_LACK
        };
    }
 
    /**
     * 身份过期
     * @param {*} msg
     * @param {*} code
     * @param {*} data
     */
    authorities(msg, code, data) {
        return {
            code: code || this.CODE.AUTHORITIES,
            data,
            msg: msg || this.MESSAGE.AUTHORITIES
        };
    }
 
    /**
     * 带分页的数据对象
     * @param {*} msg
     * @param {*} code
     * @param {*} data
     * @param {*} total
     * @param {*} limit
     * @param {*} page
     */
    pageData(msg, code, data, total, limit, page) {
        return {
            code: code || this.CODE.SUCCESS,
            data,
            total,
            limit,
            page,
            msg: msg || this.MESSAGE.SUCCESS
        };
    }
 
    /**
     * 代码分页(非数据库分页)
     * @param {*} msg
     * @param {*} code
     * @param {*} data 数据列表
     * @param {*} page 当前页
     * @param {*} limit 每页大小
     */
    totalPageData(msg, code, data, page, limit) {
        let result = {
            code: code || this.CODE.SUCCESS,
            data: [],
            limit,
            page,
            total: 0,
            msg: msg || this.MESSAGE.SUCCESS
        };
 
        //分页
        if (data && limit && page) {
            if (data && data.length > 0) {
                //索引
                let index = (page - 1) * limit;
                for (let i = index; i < page * limit; i++) {
                    if (data[i]) result.data.push(data[i]);
                }
            }
            //总大小
            result.total = data.length;
        } else {
            result.data = data;
        }
        return result;
    }
}
 
module.exports = new Result();

还有个JWT 加密解密验证的工具类 ValidateTools.js 内容如下:

jsonwebtoken 是第三方模块需要安装 npm i jsonwebtoken --save

import jwt from 'jsonwebtoken';import fs from 'fs';import path from 'path';
const publicKey = fs.readFileSync(path.join(__dirname, '../../publicKey.pub'));
/** * 验证工具类 */export class ValidateTools {
    /**     * 验证解密JWT返回处理结果     * @param {*} authorities     */    validateJWT(authorities) {        try {            console.log(`validateJWT======`, authorities.substr(7));            return jwt.verify(authorities.substr(7), publicKey);        } catch (err) {            console.log(`JWT验证结果`, err);            return false;        }    }
    /**     * 获取jwttoken     * @param {*} data     * @param {*} expiresIn     */    getJWT(data, expiresIn) {        try {            return jwt.sign({                data // 你要保存到token的数据            }, publicKey, {                expiresIn //秒到期时间            });        } catch (err) {            console.log(`JWT加密错误`, err);            throw err;        }    }
}


当然如果喜欢写原生SQL的话 mysql-db.js 也是可以的

npm i mysql --save

不建议 mysql-db 和 sequelize.js 混合使用 ,在这里提出来是方便一些需要的小伙伴.

/**
 * MySQL连接池工具
 */
import mysql from 'mysql';
import {
    DB
} from '../config';
 
class DBUtil {
 
    /**
     * 配置文件
     */
    constructor() {
        this.mysqls = {};
        this.dbNames = {};
        DB.relationalConfs.forEach(item => {
            if (!this.mysqls[`${item.dbName}Util`]) {
                this.mysqls[`${item.dbName}Pool`] = mysql.createPool({
                    connectionLimit: item.pool.max,
                    host: item.host,
                    user: item.username,
                    password: item.password,
                    database: item.database,
                    multipleStatements: true //是否允许执行多条sql语句
                });
 
                //多个连接池
                this.mysqls[`${item.dbName}Pool`].getConnection((err, connection) => {
                    if (err) throw new Error(err);
                    this[`${item.dbName}Con`] = connection;
                    console.log(`数据库 ${item.dbName} 连接成功!`);
                });
                this.dbNames[item.dbName] = item.dbName;
            }
        });
    }
 
    /**
     * 多条件查询列表
     * @param {*} dbName
     * @param {*} sql
     * @param  {Array} params
     */
    queryList(dbName, sql, ...params) {
        if (dbName) throw new Error(`参数不齐!!!`);
        console.log(`查询数据SQL:${sql},参数:`, params);
        return new Promise((resolve, reject) => {
            this[`${dbName}Con`].query(sql, params, (error, res) => {
                if (error) throw new Error(error);
                console.log(`查询结果:`, res);
                resolve(res);
            });
            this[`${dbName}Con`].release();
        });
    }
 
    /**
     * 查询对象
     * @param {*} sql
     * @param {*} params
     */
    queryObject(dbName, sql, params) {
        if (dbName) throw new Error(`参数不齐!!!`);
        console.log(`查询数据SQL:${sql},参数:`, params);
        return new Promise((resolve, reject) => {
            this[`${dbName}Con`].query(sql, params, (error, res) => {
                if (error) throw new Error(error);
                console.log(`查询结果:`, res);
                if (res && res.length > 0) {
                    resolve(res[0]);
                } else {
                    resolve(null);
                }
            });
            this[`${dbName}Con`].release();
        });
    }
 
    /**
     * 单条件查询列表数据
     * @param {*} sql SQL语句
     * @param {*} params  数据条件
     */
    queryListSingle(dbName, sql, params) {
        if (dbName) throw new Error(`参数不齐!!!`);
        console.log(`查询数据SQL:${sql},参数:`, params);
        return new Promise((resolve, reject) => {
            this[`${dbName}Con`].query(sql, params, (error, res) => {
                if (error) throw new Error(error);
                console.log(`查询结果:`, res);
                resolve(res);
            });
            this[`${dbName}Con`].release();
        });
    }
 
    /**
     * 操作数据(批量)
     * @param {*} sql
     * @param {*} params
     */
    operateMultiple(dbName, sql, ...params) {
        if (dbName) throw new Error(`参数不齐!!!`);
        console.log(`操作数据SQL:${sql},参数:`, params);
        return new Promise((resolve, reject) => {
            this[`${dbName}Con`].query(sql, params, (error, res) => {
                if (error) throw new Error(error);
                console.log(`操作结果:`, res);
                resolve(res);
            });
            this[`${dbName}Con`].release();
        });
    }
 
    /**
     * 操作单个数据
     * @param {*} sql
     * @param  {Array} params
     */
    operateSingle(dbName, sql, params) {
        if (dbName) throw new Error(`参数不齐!!!`);
        console.log(`操作数据SQL:${sql},参数:`, params);
        return new Promise((resolve, reject) => {
            this[`${dbName}Con`].query(sql, params, (error, res) => {
                if (error) throw new Error(error);
                console.log(`操作结果:`, res);
                resolve(res);
            });
            this[`${dbName}Con`].release();
        });
    }
}
 
module.exports = new DBUtil();
 
/*
relationalConfs: [{
    DB_type: 'mysql', // 数据库类型
    dbName: 'database1', //命名为唯一 调用的时候
    host: 'localhost', // 服务器地址
    port: 3306, // 数据库端口号
    username: 'root', // 数据库用户名
    password: 'root', // 数据库密码
    database: 'database1', // 数据库名称
    //prefix: 'api_', // 默认"api_"
    dialectOptions: { // MySQL > 5.5,其它数据库删除此项
      charset: 'utf8mb4',
      collate: 'utf8mb4_unicode_520_ci',
      supportBigNumbers: true,
      bigNumberStrings: true
    },
    pool: {
      max: 50, // 连接池中最大连接数量
      min: 0, // 连接池中最小连接数量
      idle: 10000 // 如果一个线程 10 秒钟内没有被使用过的话,那么就释放线程
    }
  },
  {
    DB_type: 'mysql', // 数据库类型
    dbName: 'database2', //命名为唯一 调用的时候
    host: 'localhost', // 服务器地址
    port: 3306, // 数据库端口号
    username: 'root', // 数据库用户名
    password: 'root', // 数据库密码
    database: 'database2', // 数据库名称
    //prefix: 'api_', // 默认"api_"
    dialectOptions: { // MySQL > 5.5,其它数据库删除此项
      charset: 'utf8mb4',
      collate: 'utf8mb4_unicode_520_ci',
      supportBigNumbers: true,
      bigNumberStrings: true
    },
    pool: {
      max: 50, // 连接池中最大连接数量
      min: 0, // 连接池中最小连接数量
      idle: 10000 // 如果一个线程 10 秒钟内没有被使用过的话,那么就释放线程
    }
  }
],
 */