Nodejs数据库的使用

时间: 2023-11-14 admin 维修知识

Nodejs数据库的使用

Nodejs数据库的使用

Hi I’m Shendi


Nodejs数据库的使用-Mysql
Nodejs专栏



数据库是后端中不可或缺的,而 Nodejs 自然也有与数据库相应的库来使用,Mysql数据库可以使用mysql库



安装依赖

执行以下命令安装 mysql 依赖

npm install mysql

依赖对应的github地址:


通过 requires('mysql') 引入依赖



创建连接

通过 createConnection 创建连接

示例如下

var mysql = require('mysql');
var connection = mysql.createConnection({host : 'localhost',user : 'root',password : '123456'
});

连接选项

如果你使用BIGINT,这里需要注意

  • supportBigNumbers
  • bigNumberStrings
名称默认值描述
hostlocalhost要连接的数据库的主机名
port3306连接的端口号
localAddressTCP连接使用的源IP地址(可选)
socketPath要连接到的unix域套接字的路径。使用时 host 和 port 将被忽略。
user进行身份验证的MySQL用户名
password该MySQL用户的密码
database连接使用的数据库的名称(可选)
charset‘UTF8_GENERAL_CI’连接的字符集。这在MySQL的SQL级别中被称为“排序规则”(如utf8_general_ci)。如果指定了SQL级别的字符集(如utf8mb4),则使用该字符集的默认排序规则
timezone‘local’MySQL服务器上配置的时区。这用于将服务器日期/时间值强制转换为JavaScriptDate对象,反之亦然。这可以是“local”、“Z”或形式为+HH:MM或-HH:MM的偏移量
connectTimeout10000初始连接到MySQL服务器之前的超时毫秒数
stringifyObjectsfalse将对象转换为字符串,而不是转换为值
insecureAuthfalse允许连接到要求使用旧(不安全)身份验证方法的MySQL实例
typeCasttrue确定是否应将列值转换为原生的JavaScript类型
queryFormat自定义查询格式函数。参见Custom format。
supportBigNumbersfalse在数据库中处理大数字(BIGINT和DECIMAL列)时,应启用此选项
bigNumberStringsfalse如果同时启用 supportBigNumbersbigNumberStrings,则强制将大数字(BIGINT 和 DECIMAL 列)作为 JavaScript String 对象返回。启用supportBigNumbers,但禁用bigNumberStrings,只有当它们不能用[JavaScriptNumberobjects]准确表示时,才会将大数字作为String对象返回()(当它们超过[-253,+253]范围时会发生这种情况),否则它们将作为number对象返回。如果禁用supportBigNumbers,则会忽略此选项。
dateStringsfalse强制将日期类型(TIMESTAMP、DATETIME、DATE)作为字符串返回,而不是膨胀为 JavaScript Date 对象。可以是 true/false 或保留为字符串的类型的数组
debugfalse将协议详情打印到 stdout。可以是 true/false 也可以是应该打印的数据包类型名称的数组
tracetrue在 Error 上生成堆栈跟踪,包括库入口的调用现场(“长堆栈跟踪”)。大多数调用会有轻微的性能损失
localInfiletrue允许 LOAD DATA INFILE 使用 LOCAL修饰符
multipleStatementsfalse允许每个query使用多个 mysql 语句。小心使用此功能,它可能会增加 SQL注入攻击的范围
flags除默认值之外的其他连接标志列表。也可以使用黑名单禁用默认标志。有关更多信息,请查看连接标志。
ssl具有 ssl 参数的对象或包含 ssl 配置文件名的字符串。

除了上面这种传递对象参数的方式,还可以直接通过字符串创建

var connection = mysql.createConnection('mysql://user:pass@host/db?debug=true&charset=BIG5_CHINESE_CI&timezone=-0700');


通过 connect 进行连接

connection.connect(function(err) {if (err) {console.error('连接失败: ' + err.stack);return;}console.log('连接成功,id ' + connection.threadId);
});connection.query('SELECT 1', function (error, results, fields) {if (error) throw error;// connected!
});

当然,直接使用 query 也可以隐式进行连接

connection.query('SELECT 1', function (error, results, fields) {if (error) throw error;// connected!
});


通过连接池

该模块提供了内置的连接池,而不是逐个创建和管理连接

直接使用连接池的方式,这样就不需要关心连接问题

通过 createPool 创建连接池

示例如下

var mysql = require('mysql');
var pool  = mysql.createPool({connectionLimit : 10,host : 'sdpro.top',user : 'Shendi',password : '123456',database : 'db'
});pool.query('SELECT 1 + 1 AS solution', function (error, results, fields) {if (error) throw error;console.log('The solution is: ', results[0].solution);
});

直接使用 pool 进行操作可能每次使用的连接都不一样,有的时候会需要同一个连接执行多个语句,例如事务,这时可以通过 getConnection 来从连接池获取一条连接

示例如下

var mysql = require('mysql');
var pool  = mysql.createPool(...);pool.getConnection(function(err, connection) {// 没有连接if (err) throw err;// 使用连接connection.query('SELECT something FROM sometable', function (error, results, fields) {// 操作完后将连接释放(回归连接池)connection.release();// Handle error after the release.if (error) throw error;// Don't use the connection here, it has been returned to the pool.});
});

如果您想关闭连接并将其从池中删除则使用 connection.destroy()



连接池选项

在创建连接池时候传递的Obj选项,连接池拥有连接的所有选项,除此之外,还有以下选项

名称默认值描述
acquireTimeout10000连接获取过程中发生超时前的毫秒数。这与connectTimeout略有不同,因为获取池连接并不总是涉及建立连接。如果连接请求已排队,则该请求在队列中花费的时间不计入此超时
waitForConnectionstrue确定当没有可用连接并且已达到限制时池的操作。如果为true,则池将对连接请求进行排队,并在连接请求可用时调用它。如果为false,则池将立即回调并返回错误
connectionLimit10一次创建的最大连接数
queueLimit0池在从getConnection返回错误之前可以排队的最大连接请求数。如果设置为0,则对排队的连接请求没有限制

连接池事件
acquire

当从池中获取连接时,池将发出“获取”事件。这是在连接上执行了所有获取活动之后调用的,就在连接被移交给获取代码的回调之前

pool.on('acquire', function (connection) {console.log('Connection %d acquired', connection.threadId);
});

connection

当在池中建立新连接时,池将发出“连接”事件。如果在使用连接之前需要在连接上设置会话变量,则可以侦听“connection”事件

pool.on('connection', function (connection) {connection.query('SET SESSION auto_increment_increment=1')
});

enqueue

当回调已排队等待可用连接时,池将发出“入队”事件。

pool.on('enqueue', function () {console.log('Waiting for available connection slot');
});

release

当连接释放回池时,池将发出“释放”事件。这是在对连接执行了所有发布活动之后调用的,因此在事件发生时,连接将被列为空闲

pool.on('release', function (connection) {console.log('Connection %d released', connection.threadId);
});


增删改查操作

不管增删改查都是使用 query


执行query的最基本方法是对对象(如Connection、Pool或PoolNamespace实例)调用 query 方法

query 最简单的形式是 query(sqlString, callback),其中sqlString是sql语句,callback是回调函数

connection.query('SELECT * FROM `books` WHERE `author` = "David"', function (error, results, fields) {// error发生错误则为Error// results是查询的结果// fields是返回的结果字段信息(如果有)
});

第二种形式,像预编译,但实际上它只是在内部使用相同的connection.eescape 方法。防sql注入(在这里称为转义,查阅 escaping query values)

query(sqlString, values, callback)

其中 values 是参数列表,例如

connection.query('SELECT * FROM `books` WHERE `author` = ?', ['David'], function (error, results, fields) {});

也可以像下面这样

connection.query({sql: 'SELECT * FROM `books` WHERE `author` = ?',timeout: 40000, // 40svalues: ['David']
}, function (error, results, fields) {
});connection.query({sql: 'SELECT * FROM `books` WHERE `author` = ?',timeout: 40000, // 40s},['David'],function (error, results, fields) {// error will be an Error if one occurred during the query// results will contain the results of the query// fields will contain information about the returned results fields (if any)}
);// 如果查询只有一个替换字符(?),并且该值不是null、未定义或数组,则可以将其作为第二个参数直接传递给.query
connection.query('SELECT * FROM `books` WHERE `author` = ?','David',function (error, results, fields) {}
);


事务

使用连接的 beginTransaction 开启事务,接收一个回调函数,需要手动对连接进行回滚(rollback)或提交(commit)

示例如下

connection.beginTransaction(function(err) {if (err) { throw err; }connection.query('INSERT INTO posts SET title=?', title, function (error, results, fields) {if (error) {return connection.rollback(function() {throw error;});}var log = 'Post ' + results.insertId + ' added';connection.query('INSERT INTO log SET data=?', log, function (error, results, fields) {if (error) {return connection.rollback(function() {throw error;});}connectionmit(function(err) {if (err) {return connection.rollback(function() {throw err;});}console.log('success!');});});});
});


工具类

我封装的工具类如下

var mysql = require('mysql');/*** Sql工具类<br>* @authro 砷碲*/
class SqlUtil {/** 连接池 */static pool = mysql.createPool({host : 'localhost',port : 3306,user : 'root',password : 'pwd',database : 'db',supportBigNumbers : true,multipleStatements : true,connectionLimit : 5,});/*** 执行sql语句. Promise.* 示例* exec("SELECT * FROM xx WHERE id=?", [1]).then((results,fields) => {*  console.log(results, fields);* }).catch((err) => {*  console.error("查询失败:", err);* });* @param {any} obj sql字符串或者参数对象,* @param {Array} escaping 转义列表,对应sql字符串的问号,可选*/static exec(obj, escaping) {return new Promise((resolve, reject) => {if (typeof obj == 'string') obj = { sql: obj };if (escaping) obj.values = escaping;SqlUtil.pool.query(obj, function (error, results, fields) {if (error) {reject(error);} else {resolve(results, fields);}});});}}module.exports=SqlUtil;

将其挂载到全局,所有js可用

global.SqlUtil = require("./SqlUtil");



END