Node.js---05、node.js的三方模块之MySQL


声明:本文转载自https://my.oschina.net/u/3563169/blog/1571598,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

一、第三方模块的使用和数据库访问的通用步骤

    1、第三方模块的使用步骤

    Node.js 的第三方模块的使用基本上是两个步骤:

    第一步:安装三方模块: npm install 模块名 或者 cnpm install 模块名;

    第二步:加载模块。

    其实,Node.js 对 NoSql (Not only sql 不仅仅是SQL,非关系型数据库)数据库支持度比较好。非关系型数据库集成JS的执行环境,BOSN数据类型进行存放。典型的非关系型数据库是MongoDB等。然而我没有接触过非关系型数据库,这里就使用MySQL了。

    2、访问数据库的通用操作

    第一步:创建数据库的连接并建立连接

    第二步:执行 sql 语句

    第三步:处理结果集

    第四步:关闭数据库连接

二、第三方模块 MySQL 模块

    1、简单的使用

        1.1 创建数据库的连接对象 : createConnection( )

        const conn = mysql.createConnection( opt )

        opt 是数据库连接信息的配置,

        let opt = { host:"127.0.0.1", port:"3306", user:"root", password:"", database:"数据库名" };

        1.2 执行 sql 语句 : query( )

        conn.query(sql [,params] , callback(error , result , fields) )

        let sql = “select * from 表名”;

        回调函数callback有三个参数:

                error:执行错误信息,执行成功返回null;

                result: 返回执行sql语句的结果。受影响的行数和执行时间,以及执行查询操作的查询结果。

                fields: 表的结构和字段类型

        query( ) 方法会自动执行建立连接的方法

        conn.query(sql ,(error , result , fields )=>{ ...... });

        1.3 处理结果集

        conn.query(sql ,(error , result , fields )=>{ 处理结果集 });

        1.4 关闭连接

        方法一:conn.end( )

            延迟等待关闭:接受到关闭信号之后,不立即结束和数据库的连接,等待所有的sql执行完成后再释放资源。

        方法二:conn.destroy( )

            立即关闭:接收到关闭信号后,立即释放资源,不关心是否存在尚未完成的sql。

        通常我们使用 conn.end( ) 关闭连接,需要重启或者关闭服务器时使用conn.destroy( )。

    代码事例

// 第三方模块使用 // 下载第三方模块 // 加载三方模块 const mysql = require("mysql");  // 访问数据库操作 // 1. 创建数据库 //  1.1 配置数据库信息 let opt = {     host: "127.0.0.1",     port:"3306",     user:"root",     password:"",     database:"数据库名" }; //  1.2 创建数据库连接对象 const conn = mysql.createConnection(opt); //  1.3 连接数据库,用于测试连接 // conn.connect((error)=>{ //     console.log(error); // })  // 2 执行 sql 语句 //  2.1 sql 语句 let sql =" select * from t_user"; //  2.2 执行sql语句,query()方法中自带建立连接方法,所以不需要再连接数据库 conn.query(sql,(error,result,fields)=>{     //  3 处理结果集     //   简单的打印出结果     console.log(error);     console.log(result); }); // 4 关闭数据库连接 conn.end(); 

    2、数据库连接参数

        mysql.createConnection(opt)中的opt是数据库的连接参数,具体配置信息如下:

// opt 的配置项 const mysql = require("mysql");  let opt = {     host:"127.0.0.1",     port:"3306",     user:"root",     password:"",     database:"数据库名"     // 参数项很多,注意常用选项     // 参数的解释     /*         host: 数据库连接地址 (Default: localhost) HTTP 协议连接         port: 数据了连接端口 (Default: 3306)         user: 数据库连接用户名         password: 数据库连接密码         database: 默认连接库的指定         charset: 连接数据的默认字符集 (Default: 'UTF8_GENERAL_CI')  sql :set names utf8;         timezone: 设置数据的仿佛闻时区,当前程序运行的本地时区 +HH:MM or -HH:MM. (Default: 'local')          localAddress: 集群服务器数据库连接 (TCP/IP)         socketPath: 套接字通信地址 广域网IP连接方式 (连接UNIX通信连接地址)                  connectTimeout: 连接超时时间 (Default: 10000ms)         stringifyObjects: 是否将对象强制装换为字符串格式 (date time  datetime year ) (Default: false)         dateStrings: 是否开启时间和字符串的自动转换,(Default: false)         typeCast: 是否开启数据的格式转换   (int,float……)=>number  varchar=>string date=>Date …… (Default: true)          bigNumberStrings: 高精度数值存储转换  将超过js Number 可以存放的数值转换为字符串进行转换,以保持精度         debug: 是否开启调试模式 (Default: false)          insecureAuth: 是否可以使用旧连接信息进行认证登录(Default: false)                  queryFormat: 查询语句占位符定义(查询占位符)         supportBigNumbers: 是否可以直接使用数据库大数据存储模式 (Default: false).                                    trace: 是否可以消息跟踪模式 (Default: true)         multipleStatements:  是否可以在一个query方法中执行 多条 sql (Default: false)         flags: 数据库的连接标识符         ssl: 加密连接信息     */ };

    3、占位符  ?和 ??

        在conn.query(sql [,params] , callback(error , result , fields) )方法中有个参数 params,用来携带sql语句中的占位符(?或者 ??)所代表的变量。

        如:let sql = "select * from t_user where userTel = ? ";

              let params = 电话号码;

              conn.query(sql , params ,callback(error , result ,fields) )。

        这样在执行sql语句时,等价于 let sql = "select * from t_user where userTel = 电话号码 "。

        params 参数的 sql 拼接方式取决于 params 的数据类型,常见的是 Number、String、Boolean、Array、Object物种使用方法。具体字母使用,见下:

        3.1 占位符 ‘?’:值替换符

/*     Numbers 不做任何操作直接替换一个 ?          let no = 1;         select * from table where id = ?          select * from table where id = 1      Strings 将值 包裹在  ' '  之间进行 一个 ? 替换         let name = "tom";         select * from table where name = ?          select * from table where name = 'tom'      Booleans 会被替换成 true/false   替换一个 ?         数据库会将  true  替换为 1                   false 替换为 0          Date 被转化为 'YYYY-mm-dd HH:ii:ss' 字符串         数据库会根据类型自动识别      Buffers 将缓存对象转换为 HEX 编码 替换一个 ?         会在  十六进制前  增加 X   ==>  数据库会根据类型自动转换      undefined 或 null 转换为  NULL      NaN 和 Infinity  不转换直接报错         NaN (值) ==> 意思叫做不是数值  类型 Number         Infinity (值)  ==>  意思是无穷  类型 Number       Arrays 一维数组会被转换为 固定格式  '值'   '值'   '值'    ……  值得个数替换多个 ?               其中 ''  取决于元素值得类型               let arr = ["a",2,new Date(),true];               let sql = insert into table (c1,c2,c3,c4) values (?,?,?,?);                         insert into table (c1,c2,c3,c4) values ('a',2,'YYYY-MM-DD HH:ii:ss',true);             多维数组 (二维) ['值','值','值'…… ]    ['值','值','值'…… ]  以一维数组的元素个数为基准替换对应的 ?个数             let arr = [[1,2,3],[4,5,6]];                 1,2,3   ==>  ?                 4,5,6   ==>  ?                 in(v,v,v)                 not in(v,v,v)          Objects {key:value}  ==>  存放具有关联性的数据  ==>  {name:"aaa",nikeName:"bbbb",loginName:"ccc",pwd:"dddd"}             转换规则  {key1:value1,key2:value2}  ==>  一个整体  key1=value1,key2=value2  ==> 用于替换一个 ?             update table set cName=value,cName=value,……              let user = {nikeName:"tom",userTel:"123456",password:"123",userImgUrl:"ssss.png"}             --- insert into table (……) values (?,?,?,?);             insert into table set 列名=值,列名=值,……             ==> insert into table set ?        ArraysAndObjects    [{},{}]             {} => 替换一个 ? ==>  key1=value1,key2=value2             {} => 替换一个 ? ==>  key1=value1,key2=value2      ObjectsAndArrays    {key1=[a,b],key2=[c,d]}             key1=[a,b],key2=[c,d]  ==> 替换一个 ?       例如         select * from t_user where id in( ? ) and userTel = ?;         let params = [[],String]          update t_user set ? where id = ?;         let params = [{},number]          ……       */   

        3.2 占位符 ‘??’:列替换符

        在用 “?” 替换时,会多出 ‘ ’,但是在 sql 语句中列名表名没有单引号,若用 “?” 替换时,会报错。此时就会用到 ‘??’。

    4、数据库连接池

        4.1 连接池介绍

        百度百科:连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。而连接的建立、断开都由连接池自身来管理。同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数以及每个连接的最大使用次数、最大空闲时间等等。也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。

        个人理解:在服务器启动的时候,建立多个数据库连接放入连接池。每当用户访问数据库时,直接从连接池中取出一个已建立的空闲连接对象,对数据库进行操作。使用完成后,该连接转为空闲状态,等待用户再次使用(不会关闭连接)。若用户访问数据库时连接池中没有空闲连接,则该用户进入等待队列等待空闲的连接对象(队列先进先出原则,栈先进后出原则)。

        4.2 连接池的使用方法

        第一步:创建连接池。先配置数据库连接参数设置,然后再创建连接池:const pool = mysql.createPool(opt)

        第二步:获取连接池中空闲对象 pool.getConnection((error,conn)=>{...});

        第三步:执行 sql 语句conn.query(sql ,callback);

        第四步:处理结果集

        第五步:释放当前连接pool.releaseConnection(conn);

        具体使用到代码如下:

const mysql = require("mysql");  // 1. 创建连接池 //   1.1 数据库连接参数设置 let opt = {     // 数据库连接池参数 包含 数据库创建方法createConnection中的所有参数     host: "127.0.0.1",     port: "3306",     user: "root",     password: "",     database:"tournote"      // 连接池特有参数,包括 初始化时空闲的连接对象个数、队列等待方式、连接池超时时间等      // acquireTimeout: 获取连接时的 超时时间 (Default: 10000ms)     // waitForConnections: 用户请求连接时,如果没有空闲连接或者连接上限处理方式 (Default: true)     //                     true:用户继续等待     //                     false:直接拒绝用户请求     // connectionLimit: 在连接创建时 该属性只被执行一次:初始化连接池空闲连接数量. (Default: 10)     // queueLimit: 队列允许 最大的等待用户数 (Default: 0)     //                 0 ==>   无上限值 } //  1.2 创建连接池 const pool = mysql.createPool(opt);  // 2. 获取连接池中空闲对象 // pool.getConnection(callback(error,conn)); // error 表示获取对象是否成功,成功时返回 null // conn 成功后返回的连接对象 pool.getConnection((error,conn)=>{     if(error){//获得到空闲连接对象时,返回null,所以error不为null时表示未获得空闲连接对象         console.log("获取连接池中空闲连接失败"+error.message);         return;     }     // 3. 执行 sql 语句     let sql = "select * from t_user";     conn.query(sql,(error,result,fields)=>{         // 4. 处理结果集         if(error){             console.log("执行失败");             return;         }         console.log(result);     });     // 5. 释放当前连接     pool.releaseConnection(conn); });

    5、封装工具模块

    封装数据库连接工具模块(类似于java语言对工具类),可以简化在项目对于同一个数据库进行操作时 重复定义代码。

    作用:不需要重复创建、配置参数和重复获取数据库连接,将结果交给用户自己处理。

    具体封装的工具模块如下:其中用到了连接池技术和es6 中 promise。

    注意:下属代码中,exec = function (sql ,params) {....}应该改为exec = function (sql="select 1",params=[]) {....}。这里之所以写错,是为了代码显示颜色,可读性好。这里应该是编译器到漏洞。若我正确写,下述代码将变成全白一片。

// 获取 node.js 的第三方模块 mysql const mysql = require("mysql");  // 数据库连接参数设置 let opt = {     host:"127.0.0.1",     port:"3306",     user:"root",     password:"",     database:"数据库名" } // 创建连接池 const pool = mysql.createPool(opt);  // 定义执行函数  //这里注意了,注意!注意!这里参数sql和params应该有默认值,但是开源中国博客这里的编译器有点问题,加上参数代码代码高亮显示就没了,阅读性太差 const exec = function(sql,params){//这里参数sql和params应该有默认值,像这样sql="select 1",params=[]     return new Promise((resolve,reject)=>{         // 执行sql 获取结果         pool.query(sql,params,(error,result,fields)=>{             if(error){                 reject(error);                 return;             }             let obj = {                 "result":result,                 "fields":fields             }             // Node.js 中 Promise 的resolve 方法只能接受一个参数             resolve(obj);             // resolve({result,fields})         });     }); }  module.exports = {     exec }

    本工具类的使用:

// 1、加载工具模块 const { exec } = require("./dbUtil");  // 2、编写sql let sql1 = "select * from t_user where nikeName = ? "; let sql2 = "select * from t_tour where userId = ? ";  let nikeName = ["haha"];  // 3、执行sql(调用exec()方法), promise的方法,成功执行.then()方法,失败执行.catch()方法 exec(sql1,nikeName).then(({result,fields})=>{     console.log(result[0].id);     return exec(sql2,result[0].id); }).then(({result,fields})=>{     console.log(result); }).catch((error)=>{     console.log(error.message); });

 

--本文结束,感谢您的阅读。

本文发表于2017年11月11日 20:33
(c)注:本文转载自https://my.oschina.net/u/3563169/blog/1571598,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 1777 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1