【H2O2|全栈】Node.js与MySQL连接

目录

前言

开篇语

准备工作

初始配置

创建连接池

操作数据库

封装方法

结束语


前言

开篇语

本节讲解如何使用Node.js实现与MySQL数据库的连接,并将该过程进行函数封装。

与基础部分的语法相比,ES6的语法进行了一些更加严谨的约束和优化,因此,在之后使用原生JS时,我们应该尽量使用ES6的语法进行代码编写。

准备工作

软件:【参考版本】Visual Studio Code,Postman或Apifox,Navicat Premium 16

**插件(扩展包):**Live Server

系统版本: Win10/11

提示:node.js在当前文件夹下使用cmd运行,不在浏览器解析运行

初始配置

当然,首先我们需要进行初始化得到package.json,这一步前几期已经反复提及,不再赘述。

然后,使用npm下载mysql包(记得在生产环境下),并进行导入。

我没有选择版本,配置文件中显示的版本是这个------

"dependencies": {

"mysql": "^2.18.1",

"nodemon": "^3.1.7"

}

我这里还下载了nodemon包,这样就不用编辑后反复关闭批处理程序了。

记得在scripts里面配置下面的启动语句(文件名自己起,省略后缀)------

"start": "nodemon 1.连接数据库"

最后,在我们的 1.连接数据库.js 中导入mysql包------

javascript 复制代码
// 1.导入MySQL包
const mysql = require("mysql");

创建连接池

在node.js中创建一个连接池(Pool),用于连接指定地址下的指定数据库

创建连接池的方法为createPool,它接收一个对象,该对象中有下面这些属性------

属性 作用
host 设置连接数据库的地址
port 设置端口号,MySQL端口号为3306
user 登录数据库的用户名
password 登录数据库的密码
database 使用的数据库,相当于MySQL中use的数据库

这里假设我们在本地有一个名为student的数据库,登录的用户名和密码(这个都要自己设置好哈)分别为root,123456, 那么就可以这么创建------

javascript 复制代码
// 2.创建连接池
const pool = mysql.createPool({
    host: "127.0.0.1",
    port: 3306,
    user: "root",
    password: "123456",
    database: "student"
});

操作数据库

有了连接池之后,我们就可以利用**query()**方法,直接使用MySQL的语句

比如,我们想要在student下创建一张t_students表,那么就可以先将建表的语句使用模板字符串保存起来------

javascript 复制代码
const sql = `
    CREATE TABLE t_students  (
    id int(11) UNSIGNED NOT NULL COMMENT '学号',
    name varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '姓名',
    age int(10) UNSIGNED NULL DEFAULT NULL COMMENT '年龄',
    score int(10) UNSIGNED NULL DEFAULT NULL COMMENT '分数',
    gender varchar(3) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '男' COMMENT '性别',
    comedate timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '入学时间',
    remark text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '备注',
    PRIMARY KEY (id) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
`

query()方法的形参列表为MySQL命令字符串和回调函数,就像下面这样------

javascript 复制代码
pool.query(sql, (error, results, fields) => {})

在回调函数中,error是错误信息,通常由throw进行抛出,而results则是数据库操作的结果。

javascript 复制代码
pool.query(sql, (error, results, fields) => {
    if (error) throw error;
    console.log(results);
})

至此,整个连接的基本步骤已经全部完成,下面在cmd中运行npm start,不出意外是可以看到类似下面的成功创建信息的------

使用Navicat Premium 16连接目标地址的数据库(这里是本地),打开student库,就可以看到我们刚刚创建好的t_students表------

对于其他的MySQL语句,只需要替换sql字符串的内容然后效仿即可。

注意,对于查询操作,查询的结果是一个RowDataPacket数组的形式。

我们可以使用JSON的stringify() 方法进行转化,然后利用**parse()**方法进行解析,这样就可以把结果转化成我们熟悉的JSON对象数组的形式------

封装方法

纵观node.js操作MySQL的过程,其实还是比较固定的------无非就是创建连接池和操作数据库这两步。因此,我们可以将它们封装成一个方法。

首先,建立一个db文件夹,用于保存我们的数据库操作的js文件。connect.js 用于连接池的创建,tools.js用于数据库的操作。

在connect中添加下面的代码------

javascript 复制代码
// 1导入mysql包
const mysql = require("mysql")
// 2 创建连接池
const pool = mysql.createPool({
    host: "xxx.xxx.xxx.xxx",
    port: 3306,
    user: "xxx",
    password: "xxx",
    database: "xxx"
})

module.exports = pool

这里的3360是固定的,而xxx需要根据使用者的不同替换成一些固定的代码,比如连接地址固定用户名密码指定数据库

最后,使用module.exports进行匿名导出。

对于异步的数据库操作来说,可以使用Promise进行封装。

query()方法的回调函数接收error和results参数,对应Promise的rejected()和resolved()方法。

query()的第一个参数照例还是MySQL语句,但是我们还需要在该参数和回调函数之间插入一个sqlParams参数,该参数默认为空数组,代表需要查询的数据。

对于查询语句来说,实际上是将sql参数和sqlParams拼接起来的结果,那么,为什么不在sql参数中一次性传入完整的查询语句呢?

这里假设我们在进行一次登录校验操作,那么,我们的sql参数大致是下面这样------

javascript 复制代码
const sql = `
    SELECT username, password 
    FROM table_login 
    WHERE username = 'admin' AND password = 123456
`

其中admin和123456是用户输入的值。

看上去这个校验没有任何问题,但是试想一种极端的情况,假设用户在密码框输入下面的信息------

123456 AND 1 = 1

那么我们的sql语句将会变成下面的样子------

javascript 复制代码
const sql = `
    SELECT username, password 
    FROM table_login 
    WHERE username = 'admin' AND password = 123456 AND 1 = 1
`

这样的结果是非常危险的,只要用户名输入正确,那么无论密码是什么,整个语句都将显示为可以查询到,即可以登录。

所以为了避免这种情况,我们应该让输入信息和固定的sql语句分离。

那么,原sql语句可以改成这样------

javascript 复制代码
const sql = `
    SELECT username, password 
    FROM table_login 
    WHERE username = ? AND password = ?
`

而用户名和密码则保存在sqlParams中,以数组的形式------

javascript 复制代码
['admin', 123456]

由此就可以避免输入的安全性问题。

所以,tools中的代码如下------

javascript 复制代码
// 导入链接
const connect = require("./connect")

// MySQL操作
const execute = (sql, sqlParams = []) => {
    return new Promise((resolve, rejected) => {
        connect.query(sql, sqlParams, (error, results, fields) => {
            if (error) return rejected(error);
            resolve(JSON.parse(JSON.stringify(results)));
        });
    });
}

module.exports = execute;

最后,依然是匿名导出execute()方法。

结束语

本期内容到此结束。关于本系列的其他博客,可以查看我的Node.js专栏和MySQL专栏。

在全栈领域,博主也只不过是一个普通的萌新而已。本系列的博客主要是记录一下自己学习的一些经历,然后把自己领悟到的一些东西总结一下,分享给大家。

文章全篇的操作过程都是笔者亲自操作完成的,一些定义性的文字加入了笔者自己的很多理解在里面,所以仅供参考。如果有说的不对的地方,还请谅解。

==期待与你在下一期博客中再次相遇==

------放了挺久的【H2O2】

相关推荐
TE-茶叶蛋32 分钟前
Node.js-Phase 1 学习总结:CLI 文件管理系统
学习·node.js
前端之虎陈随易9 小时前
编程语言级别的Skill市场,AI Agent 的未来形态
前端·vue.js·人工智能·typescript·node.js
南墙上的石头11 小时前
麒麟 V10 重装人大金仓 V8R6 踩坑实录(含 MySQL 兼容模式)
数据库·mysql
执子手 吹散苍茫茫烟波13 小时前
RC 隔离级别下 MySQL InnoDB 死锁典型案例
数据库·mysql
峥无16 小时前
深入理解MySQL事务与MVCC机制
数据库·mysql
要开心吖ZSH19 小时前
MVCC 进阶:快照读 vs 当前读、幻读与 Next-Key Lock
java·数据库·sql·mysql·mvcc
万亿少女的梦16820 小时前
基于Spring Boot的天空影院电影网站系统设计与实现
java·spring boot·mysql·vue·系统设计
万亿少女的梦16820 小时前
基于Spring Boot的社区管理系统设计与实现
java·spring boot·mysql·vue·系统设计
翔云12345620 小时前
简单概括主库上 Executed_Gtid_Set 是什么时候更新的
数据库·mysql
要开心吖ZSH20 小时前
Java事务与MySQL事务的关系及MVCC通俗解析
java·开发语言·mysql·mvcc