在 Nodejs 中使用 MySQL 数据库

Nodejs 数据库连接

安装依赖 mysql2

对于 MySQL, npmjs.com 上最火的模块有两个,一个是 mysql, 另一个是 mysql2。我更倾向于 mysql2,因为这个库提供了 Promise API。虽然,封装一个 Promise API 其实也很方便。

npm install mysql2@latest

编写 mysql 连接配置

安装完成后,编写一下基础的 mysql 配置。

先在 src 目录下创建 /config 目录,在此目录中创建 database.js

// 我导入的是 mysql2/promise,这是 Mysql2 库中自带的一个 Promise 兼容。
// 这篇博客里用的是最新版本的 js 语法,用到了 async/await。
// 如果大家不使用 promise, 也可以使用官方文档的错误优先式回调函数的写法,但这篇博客就不赘述了。 
const mysql = require("mysql2/promise");

const pool = mysql.createPool({
  host: "localhost",
  port: 3306,
  user: "root",
  password: "root",
  database: "att_game",

  connectionLimit: 10,
  queueLimit: 0,
});

module.exports = pool;

创建一个 mysql 连接池就这么简单。配置项的含义也是一看便懂。

使用连接池查询数据

然后在其他 js 文件里怎么使用呢?

const pool = require("./config/database");

async function main(email) {
  if (!email) return;
  try {  
    const [
      results,   // 结果集,根据你执行的sql语句不同,可能是数组或对象等类型
      fileds,    // 查询表的字段集,是个数组。多数情况下你可能用不到这个变量
    ] = await pool.query("select * from account where email=?", [email]);
    // 使用 results
    for (const row of results)
      console.log(row);
  } catch (err) {
    console.log(err);
  }
}

若是简单的单一查询就像上面这么写就很OK了。调用 pool.query(sql: string, args: array) 就可以得到结果集和字段集合。注意一点,如果用的是这个 async/await 的写法,千万千万要包裹try {} catch () {} 处理错误信息,否则,查询一旦报错,会直接崩掉整个应用的。(try...catch... 太不优雅?最后一节会介绍一个方式来包裹错误)

大家可能也看到过有些博客写查询语句是自由拼接的,类似与下面这样:

const [
  results,   // 结果集,根据你执行的sql语句不同,可能是数组或对象等类型
  fileds,    // 查询表的字段集,是个数组。多数情况下你可能用不到这个变量
] = await pool.query(`select * from account where email=${email}`);

但是这个既不优雅,也不安全。查看文档。大家千万不要使用字符串拼接的方式了。

接下来说一下上面所说的查询函数返回的结果集的类型。

如果同一时间有好几个查询,如果使用 pool.query() 的话可能会运行在不同的连接上,甚至并行运行。所以,可以用另外一个查询方式。

const main = async () => {
  let connection;
  try {
    connection = await pool.getConnection(); // 从连接池获取一个连接

    const [results1] = await connection.query('select xxx');
    const [results2] = await connection.query('update xxx');
    const [results3] = await connection.query('delete xxx');
    const [results4] = await connection.query('insert xxx');

    // ...

  } catch (err) {
    console.log(err);
  }
  if (connection)
    connection.release(); // 不要忘记释放连接 connection
};

这一种方式,要注意一点的是,查询之后,要使用 connection.release() 把连接还给连接池。另外就是错误处理一定要做。

这些也只描述了一部分 使用方法,具体的请看 mysqljs/mysql - Github。这个库的 api 和 mysql2 的几乎是一样的,所以可以阅读这个库的文档。只是上面的示例把写法换成了 es7 的 async/await。

query() 方法的返回的结果集的类型说明

当 sql 语句是 select 查询,返回格式有点儿像下面这样,是包含了所有结果的数组。

[
  TextRow {
    uid: 10000010,
    name: 'jon',
    email: '[email protected]',
    password: '87ea9be07d37a475f33c383530bc4db46a3a30ce03ebb276b21780221d3a2a43',
    coin: 14000,
    portrait: null,
    signature: null,
    state: 0,
    pwd_salt: 'gp76354eho6posu3cauoonq3ftecacsg'
  }
]

当 sql 语句是 update 更新,返回的是一个对象。我们最有可能用到的是 affectedRows 或 changedRows。具体返回示例如下:

ResultSetHeader {
  fieldCount: 0,
  affectedRows: 1,
  insertId: 0,
  info: 'Rows matched: 1  Changed: 1  Warnings: 0',
  serverStatus: 34,
  warningStatus: 0,
  changedRows: 1
}

其中

当 sql 语句是 delete 删除,最有可能用到的依然是 affectedRows,是删除的行数。具体返回示例如下:

ResultSetHeader {
  fieldCount: 0,
  affectedRows: 1,
  insertId: 0,
  info: '',
  serverStatus: 34,
  warningStatus: 0
}

当 sql 语句时 insert 插入,最有可能用到 insertId,这个值是如果有自增 id 的话,插入的自增 id 值,需要注意的是如果其主键值超出了 js 的数字限制,我们需要在创建连接池的时候,添加配置 supportBigNumbers 让库把 id 解析成字符串,否则是会抛出错误的。另外,如果从数据库里取出超出 js 最大限制的数字时也要配置 supportBigNumbers,否则数字会被四舍五入成几百或者几千,这显然不是我们所期望的,这一点在文档里有。具体返回示例如下:

ResultSetHeader {
  fieldCount: 0,
  affectedRows: 1,
  insertId: 10000015,
  info: '',
  serverStatus: 2,
  warningStatus: 0
}

你可能感兴趣的:(在 Nodejs 中使用 MySQL 数据库)