数据持久化 – 通俗地说就是将系统内存中的数据存储到数据库等数据管理工具中, 以及将数据从数据库中取出转换成内存中数据
本篇主要介绍 mysql, redis 两种数据管理工具在node中的使用。
本篇及以后的介绍都将基于第六篇建立的系统结构。
一、redis操作
redis的使用在第二篇 session 一节中有介绍过,本篇在此简单介绍下, 推荐使用node访问redis的中间件: ioredis, ioredis 的使用细节都可以在文档 (REDADME) 中找到。
1、redis连接: 为了避免每次使用redis都去写一段连接的代码,因此有必要 redis 建立链接的过程封装成一个公共 api, 方便使用。
a、首先在配置路径 /config 下的三套环境配置文件中添加 redis 配置数据:
123456 let redisConfig = {port: 6379, //端口host: '192.168.1.100', //地址//password: 'auth', //访问密码}module.exports = { redisConfig: redisConfig } //导出b、连接 redis API, 用于建立 node 与 redisd 的网络连接, 路径 ./src/lib/, 新建文件:redis-connection.js
12345678910111213141516171819202122232425262728293031 const ioredis = require('ioredis') //引入 ioredis//根据环境变量选择导入的配置文件let redisConfig = require('../../config/dev.env.config').redisConfigif( process.env.NODE_ENV === 'test' ) {const redisConfig = require('../../config/test.env.config').redisConfig} else if( process.env.NODE_ENV === 'production' ) {const redisConfig = require('../../config/prod.env.config').redisConfig}//连接redislet clientCreate = (config, callback_) => {let redis = new ioredis(config)redis.on('connect', () => { //根据 connect 事件判断连接成功callback_(null, redis) //链接成功, 返回 redis 连接对象})redis.on('error', (err) => { //根据 error 事件判断连接失败callback_(err, null) //捕捉异常, 返回 error})}let redisConn = (options) => {let config = options || redisConfigreturn new Promise((resolve, reject) => { //返回API调用方 一个 promise 对象clientCreate(config, (err, conn) => {if(err) {reject(err) //返回 err}resolve(conn) //返回连接对象})})}module.exports = redisConn2、 使用上面写的API, 实现redis的增/删/改/查 路径 ./src/app/, 新建文件: redis/redis-test.js
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 const redisConn = require('../../lib/redis-connection.js')class RedisTest {constructor() {this.redis = null}connToredis() { //创建连接对象return new Promise((resolve, reject) => {if(this.redis) {resolve(true) //已创建} else {redisConn().then(resp => {this.redis = respresolve(true) }).catch(err => { reject(err) })}})}setCommand(id, data) { //增/改if(expire === null || expire === undefined) {this.redis.set(`test-${id}`, JSON.stringify(data)).then(resp => {console.log('set', resp)}).catch(err => {console.log('err', err)})} else {this.redis.set(`test-${id}`, JSON.stringify(data), 'ex', expire).then(resp => { //ex 为过期时间,单位为 秒console.log('set', resp)}).catch(err => {console.log('err', err)})}}getCommand(id) { //查this.redis.get(`test-${id}`).then(resp => {console.log('get', resp)}).catch(err => {console.log('err', err)})}delCommand(id) {this.redis.del(`test-${id}`).then(resp => {console.log('resp', resp)})}multiCommand(id, data) {this.redis.multi().set(`test-${id}`, JSON.stringify(data)).get(`test-${id}`).exec((err, resp) => {if(err) {console.log('err', err)} else {console.log('resp', resp)}})}}//调用上面的对象,实现redis操作let redisTest = new RedisTest() //实例对象redisTest.connToredis().then(resp => { //连接成功后,进行redis操作if(resp) {redisTest.setCommand(123456, {name: 'feifeiyu'}) //增redisTest.getCommand(123456) //查redisTest.setCommand(123456, {name: 'feifeiyu3'}) //改redisTest.getCommand(123456)//查redisTest.delCommand(123456) //删redisTest.getCommand(123456) //差redisTest.multiCommand(123457, {name: 'feifeiyu2'})}}).catch(err => {console.log('err', err)})setTimeout(() => { //再进行一次redis操作redisTest.connToredis().then(resp => {redisTest.setCommand(123458, {name: 'feifeiyu'}, 1) //过期时间 1秒setTimeout(() => { //等待过期redisTest.getCommand(123458) //过期返回结果为null}, 2000)})}, 2000)返回结果
redis 其他功能 订阅, pipeline等功能参见 文档 ioredis二、mysql操作
MonogoDB 是node最常用的 noSQL 数据库,但是,目前来说 mysql 也是互联网公司使用最广泛的数据库之一。node 通过驱动 mysql 可以实现对mysql数据库的增、删、改、查操作。
安装: npm install –save mysql
注意: 以下内容之介绍node对mysql数据的基本操作,不涉及数据库建库建表等操作
1、 建立mysql连接, 一下只介绍myslq 的 连接池连接(pooling connection)
a、mysql 配置, 路径 ./config/*.env.config.js
12345678910 //mysql连接池连接let poolConfig = {host: 'localhost',port: '3306',user: 'root',password: 'mysql123',database: 'fei',// connectionLimit: 10,}module.exports = { poolConfig: poolConfig }b、mysql 连接, 路径 ./src/lib/, 新建文件: mysql-connection.js
12345678910111213141516171819202122232425262728293031 const mysql = require('mysql')let mysqlConf = require('../../config/dev.env.config').poolConfigif( process.env.NODE_ENV === 'test' ) {const mysqlConf = require('../../config/test.env.config').poolConfig} else if( process.env.NODE_ENV === 'production' ) {const mysqlConf = require('../../config/prod.env.config').poolConfig}let poolCreate = (config, callback_) => {const pool = mysql.createPool(config) //创建连接pool.getConnection((err, conn) => {if(err) {callback_(err, null) //有错误 回调} else {console.log('get connected')callback_(null, conn) //连接成功回调}})}let mysqlPool = (options) => {let config = options || mysqlConfreturn new Promise((resolve, reject) => {poolCreate(config, (err, conn) => {if(err) {reject(err) //出错}resolve(conn) //成功})})}module.exports = mysqlPoolc、创建数据表 user
d、dao层创建,即(实现 sql 语句操作), 路径 ./src/dao, 新建文件: mysql-dao.js
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 const mysqlPool = require('../lib/mysql-connection')class MysqlTestDao {constructor() {this.fieldType = { //数据库中各个字段数据类型id: 'INT',nick: 'VARCHAR',mobile: 'VARCHAR',family_name: 'VARCHAR',last_name: 'VARCHAR',address: 'VARCHAR',}}fieldTypeConfig(param) {let keys = Object.keys(param)keys.map(item => { //数据类型配置try {if(this.fieldType[item] == 'INT') {param[item] = Number(param[item])} else { //主要目的是为字符串数据加上引号param[item] = '\'' + param[item] + '\''}} catch (err) {return 'type error' + err}})return param}queryAll() { //查询所有数据return new Promise((resolve, reject) => {mysqlPool().then( conn => {let sql = 'select * from user;'conn.query(sql, (err, result) => {conn.release() //查询结束后释放链接池if(err) reject(err)resolve(result)})}).catch(err => {reject(err)})})}queryById(param) { //根据id查询return new Promise((resolve, reject) => {mysqlPool().then( conn => {let sql = 'select * from user where id=' + param.id + ';'conn.query(sql, (err, result) => {conn.release()if(err) reject(err)resolve(result)})}).catch(err => {reject(err)})})}insert(param) { //插入数据return new Promise((resolve, reject) => {mysqlPool().then( conn => {param = this.fieldTypeConfig(param)if(typeof param === 'string') {reject(param)}let keys = Object.keys(param)let sql = 'insert into user '+ '(nick, mobile, family_name, last_name, address) '+ 'values '+ '('keys.map((item, index) => {if(index === 0) {sql += param[item]} else {sql += ', ' + param[item]}})sql += ');'conn.query(sql, (err, result) => {conn.release()if(err) reject(err)resolve(result)})}).catch(err => {reject(err)})})}updateById(param, id) { //更新数据return new Promise((resolve, reject) => {mysqlPool().then( conn => {param = this.fieldTypeConfig(param)if(typeof param === 'string') {reject(param)}let keys = Object.keys(param)let sql = 'update user set\ 'keys.map((item, index) => {if(index === 0) {sql += item + '=' + param[item]} else {sql += ', ' + item + '=' + param[item]}})sql += 'where id=' + id + ';'console.log('sql', sql)conn.query(sql, (err, result) => {conn.release()if(err) reject(err)resolve(result)})})})}deleteById(id) { //删除数据return new Promise((resolve, reject) => {mysqlPool().then( conn => {let sql = 'delete from user where id=' + id + ';'console.log('sql', sql)conn.query(sql, (err, result) => {conn.release()if(err) reject(err)resolve(result)})})})}}module.exports = MysqlTestDaoe、 数据库使用(dao层调用),在业务逻辑目录 ./src/app/ 新建目录 mysqltest, 在 mysql 下新建 mysql-test.js, 加入一下代码。
12345678910111213141516171819202122232425262728293031323334353637383940 const MysqlTestDao = require('../../dao/mysql-dao')let mysqlTest = new MysqlTestDao()var newItem = {nick: 'feifeiyu3',mobile: '13245654313',family_name: 'xu',last_name: 'lu',address: 'hangzhou',}//查询 by idmysqlTest.queryById({id: 1}).then(resp => {console.log('query by id', resp)}).catch(err => {console.log('err', err)})//插入新数据mysqlTest.insert(newItem).then(resp => {console.log('inert', resp)}).catch(err => {console.log('err', err)})//查询所有mysqlTest.queryAll().then(resp => {console.log('queryAll', resp)}).catch(err => {console.log('err', err)})//数据更新mysqlTest.updateById({nick: 'feifieyu5', mobile: 13256788765}, 2).then(resp => {console.log('update by id', resp)}).catch(err => {console.log('err', err)})//数据删除mysqlTest.deleteById(3).then(resp => {console.log('delete by id', resp)}).catch(err => {console.log('err', err)})e 运行脚本,console 进入 mysql-test.js 所在目录, 运行命令 node –harmony mysql-test.js,即可看到相应的操作结果。
总结
本篇主要介绍了 redis 和 myslq 的 连接 API 封装, 数据的增、删、改、查。如果配合上 rest 接口(如 第四篇:koa2-web应用进阶—RESTful api),即可实现我们常用的 http 应用。如站点常见的,用户注册,注销,修改等。