koa+mysql+vue+socket.io全栈开发之数据访问篇
程序员文章站
2022-07-05 16:30:55
后端搭起大体的框架后,接着涉及到的就是如何将数据持久化的问题,也就是对数据库进行 CURD 操作。 关于数据库方案, mongodb 和 mysql 都使用过,但我选用的是 mysql ,原因: 1. 目前为止 mysql 与 mongodb 性能相差不大,尤其是 mysql 8.0 版本,速度非常 ......
后端搭起大体的框架后,接着涉及到的就是如何将数据持久化的问题,也就是对数据库进行 curd 操作。
关于数据库方案, mongodb 和 mysql 都使用过,但我选用的是 mysql,原因:
- 目前为止 mysql 与 mongodb 性能相差不大,尤其是 mysql 8.0 版本,速度非常快,查询数据是 mysql 更快,写数据方面 mongodb 则更胜一筹;
- mysql 建立 关联数据要更方便些,比如: 一对多,多对多的关系;
- mysql 作为关系型数据库,数据一致性方面更好,尤其是事务用起来更顺手;
- 本人对 sql 操作比较得心应手,毕竟大部分项目用得都是 mysql,而 mongodb 在正式些的项目上用的就少了,而且目前关系型数据库也在进化, postgrep 和 mysql 都已经支持 json了。
node-mysql
node-mysql 是用 sql 语句对 mysql 进行操作的库, 并没有使用 sequelize 这种 orm。因为我对 sql 熟悉,原生开发效率高。
连接池
连接数据库我选用 连接池的方式,这种方式能高效的利用数据库连接
//dbpool.js const mysql = require('mysql'); const dbconfig = require('../config/db'); const log = require('../common/logger'); let pool = null; /** * get the connection pool of database * 获取数据库连接池 */ exports.getpool = function () { if (!pool) { log.info("creating pool"); pool = mysql.createpool(dbconfig); } return pool; }
数据库配置文件
emoji 格式要用 utf8mb4 格式存储,所以这里连接字符集选用 utf8mb4,当然客户端和数据结果集 一样也要设置为 utf8mb4。
module.exports={ host: "localhost", port: "3306", user: "root", password: "jeff", database: "chatdb", charset : 'utf8mb4',//utf8mb4才能保存emoji multiplestatements: true,// 可同时查询多条语句, 但不能参数化传值 connectionlimit: 100 //连接数量 };
dao的编写
基本的代码编写方式如下,每个方法基本都是这么一种流程,获取数据库连接,执行 sql 语句,返回结果,处理异常。
exports.queryinfo = function (params, callback){ pool.query('select ...', params, function (error, result, fields) { if (error) { log(error); callback(false); } else callback(result) }); }
exportdao
这造成了一大堆重复的样板代码,我们需要封装它,用 javascript 高阶函数特性 很容易就能实现,同时加上 promise,调用时就能方便地用 async await 了,还有日志记录功能也加上。
const pool = require("./dbpool").getpool(); const log = require('../common/logger'); /** * export named query function */ const exportdao = opts => object.keys(opts).reduce((next, key) => { next[key] = (...args) => new promise((resolve, reject) => { if (opts[key]) args.unshift(opts[key]); log.info('====== execute sql ======') log.info(args); pool.query(...args, (err, result, fields) => {// fields is useless if (err) reject(err) else resolve(result); }); }); return next; }, {});
userdao文件为例,使用 exportdao 直接就能把里面的 key-value 对象输出为 以key 为方法名的dao方法,挂载到 module.exports 下。
const { exportdao } = require('./common'); //直接就exports里面的key值对应的方法 module.exports = exportdao({ sql: null,// 有些时候需要直接写sql count: 'select count(*) as count from user where ?', getuser: 'select * from user where ?', insert: 'insert into user set ?', update: 'update user set ? where id = ?', delete: 'delete from user where ?' }); /* 最终输出格式 module.exports = { sql:() => {}, count:() => {}, ... }*/
transaction
还有事务 transaction 的功能需要用到,来看一下 node-mysql 官方的例子,层层回调