Nodejs数据库的使用-Mysql

Hi I’m Shendi


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



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



安装依赖

执行以下命令安装 mysql 依赖

npm install mysql

依赖对应的github地址:https://github.com/mysqljs/mysql


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



创建连接

通过 createConnection 创建连接

示例如下

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

连接选项

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

  • supportBigNumbers
  • bigNumberStrings
名称 默认值 描述
host localhost 要连接的数据库的主机名
port 3306 连接的端口号
localAddress TCP连接使用的源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的偏移量
connectTimeout 10000 初始连接到MySQL服务器之前的超时毫秒数
stringifyObjects false 将对象转换为字符串,而不是转换为值
insecureAuth false 允许连接到要求使用旧(不安全)身份验证方法的MySQL实例
typeCast true 确定是否应将列值转换为原生的JavaScript类型
queryFormat 自定义查询格式函数。参见Custom format。
supportBigNumbers false 在数据库中处理大数字(BIGINT和DECIMAL列)时,应启用此选项
bigNumberStrings false 如果同时启用 supportBigNumbersbigNumberStrings,则强制将大数字(BIGINT 和 DECIMAL 列)作为 JavaScript String 对象返回。启用supportBigNumbers,但禁用bigNumberStrings,只有当它们不能用[JavaScriptNumberobjects]准确表示时,才会将大数字作为String对象返回(https://tc39.es/ecma262/#sec-ecmascript语言类型为数字类型)(当它们超过[-253,+253]范围时会发生这种情况),否则它们将作为number对象返回。如果禁用supportBigNumbers,则会忽略此选项。
dateStrings false 强制将日期类型(TIMESTAMP、DATETIME、DATE)作为字符串返回,而不是膨胀为 JavaScript Date 对象。可以是 true/false 或保留为字符串的类型的数组
debug false 将协议详情打印到 stdout。可以是 true/false 也可以是应该打印的数据包类型名称的数组
trace true 在 Error 上生成堆栈跟踪,包括库入口的调用现场(“长堆栈跟踪”)。大多数调用会有轻微的性能损失
localInfile true 允许 LOAD DATA INFILE 使用 LOCAL修饰符
multipleStatements false 允许每个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选项,连接池拥有连接的所有选项,除此之外,还有以下选项

名称 默认值 描述
acquireTimeout 10000 连接获取过程中发生超时前的毫秒数。这与connectTimeout略有不同,因为获取池连接并不总是涉及建立连接。如果连接请求已排队,则该请求在队列中花费的时间不计入此超时
waitForConnections true 确定当没有可用连接并且已达到限制时池的操作。如果为true,则池将对连接请求进行排队,并在连接请求可用时调用它。如果为false,则池将立即回调并返回错误
connectionLimit 10 一次创建的最大连接数
queueLimit 0 池在从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, // 40s
  values: ['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;
        });
      }
      connection.commit(function(err) {
        if (err) {
          return connection.rollback(function() {
            throw err;
          });
        }
        console.log('success!');
      });
    });
  });
});


工具类

我封装的工具类如下

var mysql = require('mysql');

/**
 * Sql工具类
* @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

你可能感兴趣的:(数据库,mysql)