Sequelize 多数据源配置

简介: 由于公司项目要将数据库进行优化更新,于是技术调研和选型选择了 PostgreSQL 数据库 和 Sequelize 框架,Sequelize的多数据源配置,这里提供两种解决方案,没事就进来看看吧。

1. sequelize 多数据源使用背景

由于公司项目要将数据库进行优化更新,于是技术调研和选型选择了 PostgreSQL数据库 和 Sequelize框架,原本的项目使用的是mysql数据库,直接使用mysql自带的pool写的,就是直接写sql,也是多数据源,有多少个数据库就使用多少个连接池,这种动态切换没啥技术含量,直接弄个cache用哪个就取哪个。
现在使用的SequelizeORM框架,之前的方案也是可以用的,是通过模型与数据库进行交互,多个连接使用同一个模型,那么进行增删改的时候是所有的连接都发生了增删改,问题就出现在这里,接下来开始探讨解决方案。

2. 解决方案1 之动态修改模式

上面背景提到过,我们现在使用的数据库是PostgreSQL,是可以有多个模式的,每个模式属于不同的用户,这个不是这里主要探讨的,主要是知道可以动态切换模式就ok了。

image.png

上面的图红框框标出来的就是模式,在Sequelize中,默认连接的是public模式,这里我们先实例化出一个连接,代码如下:

// sequelize.js
const {
   
   Sequelize} = require('sequelize');
const sequelize = new Sequelize({
   
   
    database: 'test', // 需要连接的数据库
    username: 'postgres', // 用户名
    password: '123456', // 密码
    host: '127.0.0.1', // IP地址
    // port: 5432, // 端口默认就是5432,可以不用配置
    dialect: 'postgres' // 选择 'mysql' | 'mariadb' | 'postgres' | 'mssql' 其一
});

module.exports = sequelize

模型中切换模式

如果不出现以外,数据库已经连上了,现在就要配置model了,上代码:

// model.js
const {
   
   Model, DataTypes} = require('sequelize');
const sequelize = require('./sequelize');
class test extends Model {
   
   
}

test.init({
   
   
    id: {
   
   
        type: DataTypes.UUID,
        primaryKey: true,
        defaultValue: DataTypes.UUIDV1,
        field: 'id',
        comment: '主键ID'
    },
    name: DataTypes.STRING
}, {
   
   
    sequelize,
    tableName: 'test',
    modelName: 'test',
});

module.exports = test

模型定义完了之后,关键点就来了,在Sequelize中有一个属性sequelize.dialect.supports.schemas,在目前v7版中,好像默认就是true,别问我为什么是好像,因为我找了很久资料没找到关于这个属性的描述,在源码中看到了的node_modules/sequelize/lib/dialects/postgres/index.js的第30行,这个属性的作用就是让你在查询的时候,查询语句变成'schemas'.'table'这样的,如果不放心可以手动设置一下这个属性为true,但是要在实例化之后设置,完了之后我们不能直接使用model,啥意思呢?直接上代码吧:

// 之前可以这样使用 model
const model = require('./model');
model.create({
   
   name: '田八'});

// 现在要这样写
const sequelize = require('./sequelize');
const model = sequelize.model('test'); // 这里对应的是model.js中的modelName属性
model.tableName.schema = 'test'; // 这里就是对应的模式名称,这一块应该封装成一个方法来使用的
model.create({
   
   name: '田八'});

这种方式我本来是不知道,也是网上查找资料的时候发现的,可以参考

解决方案2之 多链接,多数据源

因为公司的项目是多个数据库的,不是多个模式,这个架构我肯定是不会改的,因为改了又不知道要改多少代码,谁会没事去加自己的工作量呢?直接上代码吧:

// sequelize.js
const {
   
   Sequelize} = require('sequelize');
const config = {
   
   
    db_name1: {
   
   /* 这里自定义配置 */},
    db_name2: {
   
   },
    db_name3: {
   
   },
}
const connect_pool = {
   
   };

Object.entries(config).forEach(([key, value]) => {
   
   
    connect_pool[key] = new Sequelize({
   
   
        database: key,
        username: 'postgres',
        password: '123456',
        host: '127.0.0.1',
        dialect: 'postgres'
    });
});

这里的关键点还是在model中,不多说,直接上代码:

// model.js
const {
   
   Model, DataTypes} = require('sequelize');

module.exports = (sequelize) => {
   
   
    class test extends Model {
   
   
    }

    test.init({
   
   
        id: {
   
   
            type: DataTypes.UUID,
            primaryKey: true,
            defaultValue: DataTypes.UUIDV1,
            field: 'id',
            comment: '主键ID'
        },
        name: DataTypes.STRING
    }, {
   
   
        sequelize,
        tableName: 'test',
        modelName: 'test',
    });

    return test; // 这里的 return 其实要不要其实无所谓
}

这里主要使用闭包的原理进行导出,每次导出的都是一个新的model,多数据源,同时model相同可以使用这种方式(就是多个数据库表结构相同),使用的时候也很简单:

// sequelize.js
const {
   
   Sequelize} = require('sequelize');
const config = {
   
   
    db_name1: {
   
   /* 这里自定义配置 */},
    db_name2: {
   
   },
    db_name3: {
   
   },
}
const connect_pool = {
   
   };

Object.entries(config).forEach(([key, value]) => {
   
   
    connect_pool[key] = new Sequelize({
   
   
        database: key,
        username: 'postgres',
        password: '123456',
        host: '127.0.0.1',
        dialect: 'postgres'
    });
});

// 在这里直接使用就好了
const test = require('sequelize');
Object.values(connect_pool).forEach(sequelize => {
   
   
    const model = test(sequelize);
    model.create({
   
   name: '田八'});
})

优化一下

上面这种就是我现在使用的方案,当然我作为一名喜欢偷懒的程序员,肯定是要自动化注册model的,上代码:

// sequelize.js
const {
   
   Sequelize} = require('sequelize');
const config = {
   
   
    db_name1: {
   
   /* 这里自定义配置 */},
    db_name2: {
   
   },
    db_name3: {
   
   },
}
const connect_pool = {
   
   };

Object.entries(config).forEach(([key, value]) => {
   
   
    connect_pool[key] = new Sequelize({
   
   
        database: key,
        username: 'postgres',
        password: '123456',
        host: '127.0.0.1',
        dialect: 'postgres'
    });
});

// 在这里直接使用就好了
// const test = require('sequelize');
// Object.values(connect_pool).forEach(sequelize => {
   
   
//     const model = test(sequelize);
//     model.create({name: '田八'});
// })

// 优化
async function init_sequelize() {
   
   
    for (let sequelize of Object.values(connect_pool)) {
   
   
        await init_model(sequelize);
        await sequelize.sync();
    }
}

const fs = require('fs');
const path = require('path');
const init_model = (sequelize) => {
   
   
    return new Promise(resolve => {
   
   
        // 将所有的模型定义到一个目录下面,然后遍历该目录下的所有文件
        const filePath = path.resolve(__dirname, './model/');
        fs.readdir(filePath, (err, files) => {
   
   
            if (err) return;

            //遍历读取到的文件列表
            for (const filename of files) {
   
   
                // 只要js文件
                if (/.js$/.test(filename)) {
   
   
                    const init = require('./model/' + filename);
                    // 确定导出的是一个方法
                    typeof init === 'function' && init(sequelize)
                }
            }
            resolve();
        });
    })
}

init_sequelize().then(res => {
   
   
    const model = getModel('test', 'test');
    model.create({
   
   name: '田八'});
})

const getModel = (database, modelName) => {
   
   
    return connect_pool[database].model(modelName)
}

好了,任务圆满完成,这里提一个问题,曾经面试问过一个面试者一个问题,就是闭包,他直接说不常用,pass,这里model配置的关键点就是闭包,所以各位基础该打牢还是得打牢一点,不说废话,喜欢就点个赞吧!!!

目录
相关文章
|
SQL 缓存 监控
druid数据源配置参数说明
druid数据源配置参数说明
1812 0
|
Oracle Java 关系型数据库
Spring+Mybatis多数据源配置(二)——databaseIdProvider的使用
 在上一篇同系列的博文中,讲到配置多数据源,然后根据config.properties配置不同的数据库,进行切换。而且需要根据不同的数据库,配置不同的mybatis sql映射配置文件,如下: classpath...
2396 0
|
3月前
|
JavaScript 前端开发 关系型数据库
使用Sequelize8
使用Sequelize8
28 0
|
6月前
|
关系型数据库 数据库 数据安全/隐私保护
springboot+dynamic-datasource多数据源配置动态切换
springboot+dynamic-datasource多数据源配置动态切换
724 0
|
7月前
|
SQL Java 关系型数据库
SpringBoot整合JDBC与默认数据源
SpringBoot整合JDBC与默认数据源
83 0
|
关系型数据库 MySQL PostgreSQL
ruoyi数据源修改为PostgreSQL分页错误
ruoyi数据源修改为PostgreSQL分页错误
188 0
|
关系型数据库 数据库 数据安全/隐私保护
使用脚手架Scaffold-DbContext连接(SqlServer和PostgreSQL)
【代码】使用脚手架Scaffold-DbContext连接(SqlServer和PostgreSQL)
232 0
|
存储 关系型数据库 数据库连接
[Nestjs] 使用Typeorm配置数据库配置时区的方法
如果在使用 TypeORM 和 NestJS 进行数据库操作时,遇到数据库时间不准确的问题,可以考虑以下几个解决办法: 1. 使用数据库服务器的时间:确保数据库服务器的时间是准确的,并且与应用程序运行的服务器时间同步。这样可以避免由于时间差异导致的数据不准确问题。 2. 设置数据库连接的时区:通过在 TypeORM 配置中设置 timezone 属性,将数据库连接的时区设置为与应用程序所在地区相匹配。例如,对于 PostgreSQL 数据库:
830 0
|
SQL 算法 Java
springboot中sharding jdbc绑定表配置实战
springboot中sharding jdbc绑定表配置实战
|
安全 关系型数据库 PostgreSQL
PostgreSQL中插件如何新增一个配置项
PostgreSQL中插件如何新增一个配置项
189 0