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
}