【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包——

// 1.导入MySQL包
const mysql = require("mysql");

创建连接池

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

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

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

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

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

操作数据库

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

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

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命令字符串和回调函数,就像下面这样——

pool.query(sql, (error, results, fields) => {})

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

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中添加下面的代码——

// 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参数大致是下面这样——

const sql = `SELECT username, password FROM table_login WHERE username = 'admin' AND password = 123456
`

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

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

123456 AND 1 = 1

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

const sql = `SELECT username, password FROM table_login WHERE username = 'admin' AND password = 123456 AND 1 = 1
`

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

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

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

const sql = `SELECT username, password FROM table_login WHERE username = ? AND password = ?
`

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

['admin', 123456]

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

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

// 导入链接
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】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/486622.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV 图像基本操作

OpenCV快速通关 第一章:OpenCV 简介与环境搭建 第二章:OpenCV 图像基本操作 OpenCV 图像基本操作 OpenCV快速通关第二章:OpenCV 图像基本操作一、相关结构体与函数介绍(一)cv::Mat 结构体(二)c…

故障识别 | GADF-CNN-SSA-XGBoost数据分类预测/故障识别(Matlab)

故障识别 | GADF-CNN-SSA-XGBoost数据分类预测/故障识别(Matlab) 目录 故障识别 | GADF-CNN-SSA-XGBoost数据分类预测/故障识别(Matlab)分类效果基本描述程序设计参考资料 分类效果 基本描述 格拉姆角场差(GADF&#…

树莓派4B android 系统添加led灯 Hal 层

本文内容需要用到我上一篇文章做的驱动,可以先看文章https://blog.csdn.net/ange_li/article/details/136759249 一、Hal 层的实现 1.Hal 层的实现一般放在 vendor 目录下,我们在 vendor 目录下创建如下的目录 aosp/vendor/arpi/hardware/interfaces/…

基于Matlab的变压器仿真模型建模方法(9):三相变压器组的建模仿真(续)

1.引言 前一节介绍了基于混合磁链的考虑主磁路饱和情况的三相变压器组的Simulink仿真模型,并应用它对Y,yn接法三相变压器组的瞬态过程进行了仿真计算。这一节建立一个新的基于等效电路的Simulink三相变压器组的仿真模型,并应用它对Y,d11接法的三相变压器组的瞬态过程进行仿…

【Atcoder】【ABC383】A- Humidifier 1加湿器 题解

前言 不知道大家有没有关注过AtCoder 这是小日子那边的一个网站,每周都会有比赛 比起CF等等,最大的优点就是延迟低,题目质量也不错 计划以后每周更新题解了 正文 题目传送门A - Humidifier 1 题目大意 有一个加湿器,给定 …

LeetCode 热题 100_反转链表(23_206_简单_C++)(单链表_递归)

LeetCode 热题 100_反转链表(23_206) 题目描述:输入输出样例:题解:解题思路:思路一(迭代):思路二(简化方法一(迭代)代码):思路三&…

49 基于单片机的湿度和光照监测

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于AT89C52单片机,采用DHT11温湿度传感器检测土壤湿度,光敏电阻连接ADC0832数模转换器作为光敏传感器,然后通过LCD1602显示湿度和光照值,如果湿度低…

【C语言】程序设计--算法

文章目录 1. 判断两个数的大小并交换2. 计算三角形面积3. 根据x的值计算y4. 字符大小写转换5. 百钱百鸡问题6. 计算公式y的值7. 输出所有的水仙花数8. 计算n的阶乘9. 下三角数据10. 斐波那契数列11. 学生成绩统计12. 数组的平均值1. 判断两个数的大小并交换 介绍: 从键盘输入…

嵌入式Linux,字符串的处理,以及相关函数详解

C 语言库函数中已经给我们提供了丰富的字符串处理相关函数,基本常见的字符串处理需求都可 以直接使用这些库函数来实现。 1. 字符串输入/输出 在程序当中,经常需要在程序运行过程中打印出一些信息,譬如调试信息、报错信息、中间产生的变量的…

400G智算网络助力知名自动驾驶企业算力训练提效

根据Gartner的最新趋势预测,自动驾驶技术正迅速发展,预计在未来几年内将带来显著的商业效益,特别是在决策智能和边缘人工智能领域。目前,一家领军企业正积极拥抱基于大模型的数字化转型之路,作为自动驾驶领域的佼佼者&…

【iOS】OC高级编程 iOS多线程与内存管理阅读笔记——自动引用计数(三)

目录 ARC规则 概要 所有权修饰符 __strong修饰符 __weak修饰符 __unsafe_unretained修饰符 ___autoreleasing修饰符 ARC规则 概要 “引用计数式内存管理”的本质部分在ARC中并没有改变,ARC只是自动地帮助我们处理“引用计数”的相关部分。 在编译单位上可以…

数学活动是什么过程?

有专家说:数学活动是建构的操作过程,建构的过程必须是探索、发现和创造的过程。 什么是建构,建构就是构建,就是建立。明明有让人一看就明白的词,人非得弄得云遮雾绕。 也难怪,现在什么都流行上云。 上云…

windows11安装Linux子系统配置大数据hadoop

zai 1、安装linux子系统 1、启用适用于 Linux 的 Windows 子系统 搜索框里面输入<开发>即可跳转&#xff0c;打开开发人员模式 命令行里面输入systeminfo确定是否电脑已经支持虚拟化&#xff0c;是则可以继续安装: 2、然后先启用“适用于 Linux 的 Windows 子系统”可选…

RPC设计--从reactor设计 (IOthread)

主从reactor架构 一般的一个网络IO库都是主从reactor模式&#xff0c;即主线程中有一个MainReactor&#xff0c;其负责监听ListenFd&#xff0c;当接受到新的用户连接时&#xff0c;返回的clientfd并不会加入的MainReacotr&#xff0c;而是在子线程&#xff08;这里称为IO线程&…

微信创建小程序码 - 数量不受限制

获取小程序码&#xff1a;小程序码为圆图&#xff0c;且不受数量限制。 目录 文档 接口地址 请求方式 功能描述 注意事项 获取 scene 值 请求参数 返回参数 对接 请求方法 获取小程序码 调用获取小程序码 总结 文档 接口地址 https://api.weixin.qq.com/wxa/get…

【机器学习】基于SVM、逻辑回归和CNN的手写数字识别:性能对比与应用分析

基于SVM、逻辑回归和CNN的手写数字识别&#xff1a;性能对比与应用分析 1 基于SVM对手写数字识别2 基于逻辑回归对手写数字进行识别3 基于CNN对手写数字进行识别总结对比分析 1 基于SVM对手写数字识别 在使用SVM方法对手写数字进行识别的时候&#xff0c;我采用了一对多&#…

群控系统服务端开发模式-应用开发-邮件工厂电信189发送开发

一、电信189邮件工厂开发 1、添加框架对应的SDK composer require phpmailer/phpmailer 2、添加电信189邮件工厂 在根目录下extend文件夹下Mail文件夹下channel文件夹下&#xff0c;创建电信189邮件发送工厂并命名为DianxinMailSender。记住&#xff0c;一定要在电信189邮件发…

部署loki,grafana 以及springcloud用法举例

文章目录 场景docker 部署grafanadocker-compose部署loki维护配置文件 local-config.yaml维护docker-compose.yml配置启动 grafana 添加loki数据源springcloud用法举例查看loki的explore,查看日志 场景 小公司缺少运维岗位&#xff0c;需要研发自己部署日志系统&#xff0c;elk…

非常简单实用的前后端分离项目-仓库管理系统(Springboot+Vue)part 4

三十三、出入库管理 Header.vue导一下,RecordController加一个 //将入库数据和原有数据相加吧//新增PostMapping("/save")public Result save(RequestBody Record record) {return recordService.save(record) ? Result.success() : Result.fail();} GoodsManage.v…

Leetcode—1133. 最大唯一数【简单】Plus

2024每日刷题&#xff08;205&#xff09; Leetcode—1133. 最大唯一数 C 实现代码 class Solution { public:int largestUniqueNumber(vector<int>& nums) {constexpr int MAX 1000;vector<int> count(MAX 1, 0);for(int num: nums) {count[num];}for(int…