【Express.js】数据库初始化

这篇具有很好参考价值的文章主要介绍了【Express.js】数据库初始化。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

数据库初始化

        在软件开发阶段和测试阶段,为了方便调试,我们通常会进行一系列的数据库初始化操作,比如重置数据表,插入记录等等,或者在部署阶段进行数据初始化的操作

        根据前面章节介绍过的 knex.jssequelize.js,我们可以利用它们提供的方法进行DDL,本节就数据库表重置的初始化行为做一点探讨,表结果为User{id: num, name: string, age: num},数据库采用sqlite

Knex DDL

以下是利用 knex.schema 的一个简单示例:
knex.js

const knex = require('knex');
const fs = require('fs');

const sqlClient = knex({
    client: 'sqlite3',
    connection: {
        filename: `${__root}/db/data.db`,
        acquireConnectionTimeout: 1000
    },
    useNullAsDefault: true
});

module.exports = sqlClient;

init.js

global.__root = __dirname;

const knex = require('./knex.js');

const drop = knex.schema.dropTableIfExists('user');
const create = knex.schema.createTable('user', (user)=>{
    user.increments('id').notNullable().primary();
    user.text('name').notNullable();
    user.integer('age').notNullable()
});
const promises = [drop,create];
Promise.all(promises)
.then(res=>{
    console.log('Database inits successfully!')
}).catch(err=>{
    console.error(err);
})

Sequelize DDL

以下是利用 Sequelize.Model 的一个简单示例:
sequelize.js

const { Sequelize,DataTypes,Model } = require('sequelize');
const fs = require('fs');

const sqlClient = new Sequelize({
    dialect: 'sqlite',
    storage: `${__root}/db/data.db`
})

const User = sqlClient.define('User', {
    id: {
        primaryKey: true,
        type: DataTypes.INTEGER,
        allowNull: false,
        autoIncrement: true
    },
    name: {
        type: DataTypes.STRING,
        allowNull: false
    },
    age: {
        type: DataTypes.INTEGER,
        allowNull: false
    }
}, {
    tableName: 'user',
    timestamps: false,
});

module.exports = {
    sqlz: sqlClient,
    User
}

init.js

global.__root = __dirname;

const { User } = require('./sequelize');

// User.drop();User.sync();
User.sync({ force: true })  //这个相当于前两个的结合体
    .then(res=>{
        console.log('Database inits successfully!');
    }).catch(err=>{
    console.error(err);
})

SQL文件

        Springboot作为Web后端最流行的框架之一,想必各位都接触过或者听说过,在Springboot中,可以在配置文件中设置sql脚本的路径,在项目启动时执行sql脚本来完成初始化。
        这是一种非常好的方法,因为有时候我们项目场景下的数据库表结构与关系可能非常复杂,而且不同语言,不同框架的实现有些区别,用代码去完成初始化操作将是一件非常麻烦的事,既然SQL是关系型数据库通用的语言,那我们就可以通过SQL脚本来定义数据库表的结构和关系,可以手写SQL脚本,也可以借助如Navicat之类的工具设计表然后转储sql脚本,然后交给我们的程序去执行,或者手动执行。

Node的sql框架千千万,我在几个主流框架中似乎都没看到有提供执行sql文件的特性,其实没那么复杂,不从构造完美的框架角度,仅以为项目服务的角度考虑来说是这样的,接下来我们就来简单实现一下通过sql脚本去初始化数据库。

有两条路:

  1. 运行环境先安装sqlite3客户端,node读取sql脚本内容,node通过exec去指定目录下,打开sqlite3命令行连接sqlite数据库,同时把sql内容传递过去,在sqlite3中执行sql脚本完成数据库初始化操作
  2. Node安装sqlite3依赖,通过sql框架连接sqlite数据库,node读取sql脚本内容,对内容进行规范化处理只剩下纯净的sql语句后,交给sql框架以sql语句的形式去运行

Springboot采用的就是第2种方法,那我们也在Node中实现一下吧
实现准备好sql脚本 schemal.sql

-- 先删除user表
DROP TABLE IF EXISTS `user`;
-- 定义表结构,并创建user表
CREATE TABLE `user` (
    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,  --自增主键
    name TEXT NOT NULL,
    age INTEGER NOT NULL
);

Knex

先用Knex作为sql框架做个示范。获取到项目根目录路径后,建立数据库连接:
knex.js

const knex = require('knex');
const fs = require('fs');

const sqlClient = knex({
    client: 'sqlite3',
    connection: {
        filename: `${__root}/db/data.db`,
        acquireConnectionTimeout: 1000
    },
    useNullAsDefault: true
});

module.exports = sqlClient;

接下来,为客户端实现执行sql文件的方法:

  1. 定义runSql方法的传参和返回
    我这里传入sql文件的路径,返回sql语句执行的promise链
  2. 内部实现,首先通过fs模块读取sql脚本内容并转为字符串
  3. 把内容中的注释去掉
  4. 去掉内容首尾的空格
  5. 去掉\r
  6. 去掉\n(我为了打印sql语段时更加美观,省去了这一步,不影响执行结果)
  7. 把内容按照;号分割成一个个独立的sql语句字串
  8. 过滤掉空字串(由每2个sql语句间的空格形成)
sqlClient.runSql = (path)=>{
    const script = fs.readFileSync(path).toString();
    console.log("Going to run a sql file:");
    console.log(script);
    /**
     * 拆成一句句sql来执行是因为,knex执行一串语句时,会把它们都算进一个事务内
     * 利用正则忽略注释
     * 去首尾空格
     * 按冒号分句
     * 校验字串是否为sql语句
     * @type {string[]}
     */
    const sqls = script.replace(/\/\*[\s\S]*?\*\/|(--|\#)[^\r\n]*/gm, '').trim().replaceAll('\r','').split(';').filter(str=>{
        return str.trim() ? true : false;
    });
    console.log("sqls");
    console.log(sqls);
    console.log("start run:");
    const promises = sqls.map(sql=>{
        sql += ';';  // knex会自动补上冒号,加不加无所谓其实
        console.log("Going to run a sql:");
        console.log(sql);
        return sqlClient.raw(sql);
    })
    return promises;
}

到这里,我们就得到了纯净的一条条sql语句,接下来把sql语句丢给knex即可:
init.js

global.__root = __dirname;

const knex = require('./knex.js')

const promises = knex.runSql(`${__root}/db/schema.sql`);
Promise.all(promises)
    .then(res=>{
        console.log("Database inits successfully!")
    }).catch(err=>{
    console.error(err);
})

输出结果:

D:\Workstation\gitee-localRepo\express-demo\DatabaseInit>node index.js
Going to run a sql file:
-- 先删除user表
DROP TABLE IF EXISTS `user`;
-- 定义表结构,并创建user表
CREATE TABLE `user` (
    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,  --自增主键
    name TEXT NOT NULL,
    age INTEGER NOT NULL
);

sqls
[
  'DROP TABLE IF EXISTS `user`',
  '\n' +
    '\n' +
    'CREATE TABLE `user` (\n' +
    '    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,  \n' +
    '    name TEXT NOT NULL,\n' +
    '    age INTEGER NOT NULL\n' +
    ')'
]
start run:
Going to run a sql:
DROP TABLE IF EXISTS `user`;
Going to run a sql:


CREATE TABLE `user` (
    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    age INTEGER NOT NULL
);
Server is ready on http://:::8080
Database inits successfully!

很好,我们可以很清晰的看到sql的执行过程

Sequelize

        如果你把knex这套照搬过去,把knex.raw换成sequelize.query,你也许会尴尬的发现,不太对劲,它先创建了user表,接着又把它给删了,还大言不惭地打印了成功信息(我的环境下是这样,不清楚别人会不会,但既然发生了就说明存在一定的问题)。尝试反复执行knex示例和seuelize示例,前者永远正确,后者永远错误,而且sequelize似乎更慢一点,产生这样的区别,可能是它们执行sql语句的实现机制不太一样,花费精力去看它源码没有必要,既然在这个场景下我们这两个步骤有着明确的先后顺序,那我们就通过async/await让它们完全的顺序执行即可:

sqlClient.runSql = async (path)=> {
    const script = fs.readFileSync(path).toString();
    console.log("Going to run a sql file:");
    console.log(script);
    /**
     * 拆成一句句sql来执行是因为,knex执行一串语句时,会把它们都算进一个事务内
     * 忽略注释
     * 去首尾空格
     * 按冒号分句
     * 校验字串是否为sql语句
     * @type {string[]}
     */
    const sqls = script.replace(/\/\*[\s\S]*?\*\/|(--|\#)[^\r\n]*/gm, '').trim().replaceAll('\r','').split(';').filter(str=>{
        return str.trim() ? true : false;
    });
    console.log("sqls");
    console.log(sqls);
    console.log("start run:");
    for (let sql of sqls) {
        const res = await sqlClient.query(`${sql};`);
    }
}

输出结果:

D:\Workstation\gitee-localRepo\express-demo\DatabaseInit>node index.js
Going to run a sql file:
-- 先删除user表
DROP TABLE IF EXISTS `user`;
-- 定义表结构,并创建user表
CREATE TABLE `user` (
    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,  --自增主键
    name TEXT NOT NULL,
    age INTEGER NOT NULL
);

sqls
[
  'DROP TABLE IF EXISTS `user`',
  '\n' +
    '\n' +
    'CREATE TABLE `user` (\n' +
    '    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,  \n' +
    '    name TEXT NOT NULL,\n' +
    '    age INTEGER NOT NULL\n' +
    ')'
]
start run:
Server is ready on http://:::8080
Executing (default): DROP TABLE IF EXISTS `user`;
Executing (default): CREATE TABLE `user` (
    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    age INTEGER NOT NULL
);
Database inits successfully!

Ok!现在Sequelize也按照我们的意愿完成了重置user表的初始化工作


如果初始化过程中涉及严格的先后顺序,务必做好同步流甚至回滚机制。此外,在实际项目中,为了项目的代码规范性,应当将数据库路径,初始化脚本路径都写在配置文件中,而不是像本节为了方便直接写在需要调用的js文件中。文章来源地址https://www.toymoban.com/news/detail-639005.html

下一节-页面渲染

到了这里,关于【Express.js】数据库初始化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • CDH集群hive初始化元数据库失败

    oracle数据库操作: 报错如下:命令 (Validate Hive Metastore schema (237)) 已失败 截图如下: 后台日志部分摘录: WARNING: Use “yarn jar” to launch YARN applications. SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p5253.21605619/jars/log4j-slf4j-im

    2024年04月11日
    浏览(47)
  • Linux-MariaDB数据库的备份与初始化

    Linux系统下我们比较常用的数据库软件是开源又免费的MySQL。MariaDB是MySQL的一个分支,采用GPL授权许可,完全兼容MySQL的API与命令行。虽然MariaDB公司即将倒闭,但这不影响它的性能超越MySQL的事实。 使用 mysqldump 命令。这个命令可以帮助导出一个含有数据库结构与数据的SQL脚本

    2024年02月15日
    浏览(83)
  • mac系统之集成环境phpwebstudy初始化mysql数据库

    PhpWebStudy是使用electron开发的桌面应用.目前支持的软件, nginx, apache, mysql, mariaDB, php, memcached, redis, mongoDB. 安装和卸载, 全部都是通过调用homebrew和macports的内置功能. 事实上, 使用homebrew或macports自行安装卸载和在软件里操作是一样的.对于习惯使用brew或port命令的用户, 依然可以继

    2024年02月01日
    浏览(58)
  • Spring Boot实现第一次启动时自动初始化数据库

    在现在的后端开发中,只要是运用联系型数据库,信任SSM架构(Spring Boot + MyBatis)已经成为首选。 不过在咱们第一次运转或许布置项目的时分,一般要先手动衔接数据库,履行一个SQL文件以创立数据库以及数据库表格完结 数据库的初始化作业 ,这样咱们的SSM应用程序才能够

    2024年02月03日
    浏览(54)
  • openstack详解(二十三)——Neutron其他配置、数据库初始化与服务启动

    今天继续给大家介绍Linux运维相关知识,本文主要内容是Neutron其他配置、数据库初始化与服务启动。 在上文openstack详解(二十二)——Neutron插件配置中,我们完成了Neutron插件的配置,今天,我们来进行Neutron的元数据代理配置、数据库初始化以及服务启动。 打开Neutron的元数

    2024年02月10日
    浏览(58)
  • 初始化Hive元数据库 bash: schematool: 未找到命令的原因

    初始化元数据库:schematool -initSchema -dbType mysql -verbose 报错如下: 解决方法: (1)是否将MySQL的JDBC驱动拷贝到Hive的lib目录下: sudo cp /opt/software/mysql-connector-java-5.1.37.jar $HIVE_HOME/lib (2)是否在$HIVE_HOME/conf目录下新建hive-site.xml文件,文件的内容可以百度下 (3)Hive环境变量是否配置

    2024年02月13日
    浏览(36)
  • 日志审计系统Agent项目创建——初始化数据库和日志文件(Linux版本)

    完结,下一篇主要是读取日志文件,并读取最新日志文件

    2024年01月16日
    浏览(67)
  • 安装hive中初始化元数据库失败,显示Failed to get schema version

    我在搭建数据仓库的时候,安装hive包初始化元数据库失败。在网上找了几种方法都没解决成功,然后我又重新看了一下问题,问题当中还显示了:无法使用MySQL以‘root‘@‘localhost‘。 原因分析: 1、权限问题:mysql版本的驱动包不对应,一般 linux系统下的jar为后缀 2、密码问

    2024年02月05日
    浏览(45)
  • Django-drf项目初始化:跨域、认证权限过滤、static静态资源路由,mysql数据库连接,登录注册功能

    码云地址:https://gitee.com/liuhaizhang/drf-project-initialization 项目目录结构: study_drf            -home         -static         -study_drf         -util         -manage.py pip install django #drf基于django pip install djangorestframework #drf框架 pip install mysqlclient #连接数据库 pip install djangorestframewo

    2024年02月03日
    浏览(66)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包