有时候因项目需要.在koa中需要使用多个数据库和多种数据库
此以 MongoDB 和 MySQL为例
此项目中用到了2个MySQL 和 多个MongoDB,其中MongoDB的库名生成是由时间生成的如2018_11_09,这种采用动态库名链接的方式进行连接.
首先创建一个全局的配置 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 的中文文档 飞机票: https://itbilu.com/nodejs/npm/VkYIaRPz-.html
因为要导出 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 秒钟内没有被使用过的话,那么就释放线程
}
}
],
*/