Node - 操作数据库(六)

605 阅读5分钟

“Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine”官网的一句介绍大致是说“Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时”,简单来说就是一个能让JS运行在服务端的环境。

前言

Hi~ 我又回来了,这周又有点慢了,害,着实是年底事情比较多。。。

这次的主题是讲操作数据库,铁子们是不是还是有点期待。

本次以MySQL数据库为例,如果你对它完全不了解,可以点我。(不要问为什么是MySQL,问,就是不知道)

回到正题

提前准备

既然是要操作数据库,我们首先要拥有一个数据库,安装过程就不说了,反正我有了,你们就自行去某度吧。

然后借助navicat工具连接上数据库进行可视化操作(如果是大神可以直接命令操作,秀一波),创建一个user表,插入一条数据,如下:

普通连接

其实操作数据库是非常简单的,寥寥几行代码就能让我们进入数据库的大门,我们需要借助一下mysql这个依赖npm install mysql

我们直接上代码(test.js):

const mysql = require('mysql');
const db = mysql.createConnection({
  host     : 'localhost',
  user     : 'root',
  password : '12345',
  database : 'test'
});

db.connect(err => {
  if(err) throw err;
  console.log('连接成功')
});

let sql = `select * from user`; // 查
/*
let sql = `insert into user set username='yd', age=18`; // 增
let sql = `update user set username='YD' where id=2`; // 改
let sql = `delete from user where id=2`; // 删
*/

db.query(sql, (err, res) => {
  if (err) throw err;
  console.log(res); // [{ id: 1, username: '橙某人', age: 18 }]
  dbClose();
});

function dbClose() {
  db.end(err => {
    if(err) throw err;
    console.log('关闭成功');
  });
  // db.destory() 也可以关闭数据库, 但没有回调
}

以上代码只能一次性操作数据库。

是不是很简单?...我感觉有人要开喷了。。。(得闪)

连接池连接

const mysql = require('mysql');
const pool = mysql.createPool({
  host: 'localhost',
  user: 'root',
  password: '12345',
  database: 'test',
  multipleStatements: true, // 允许同时创建多个连接池
  connectionLimit: 10, // 同时创建多个连接池, 并不是创建越多越好的, 多了会消耗性能, 别人用完了连接池, 连接池应该立马回收.
});

let sql = `select * from user`; // 查
/*
let sql = `insert into user set username='yd', age=18`; // 增
let sql = `update user set username='YD' where id=2`; // 改
let sql = `delete from user where id=2`; // 删
*/

pool.getConnection((err, db) => {
  if(err) throw err;
  db.query(sql, (err, result) => {
    if (err) throw err;
    console.log(result); // [{ id: 1, username: '橙某人', age: 18 }]
    db.release(); // 释放连接池中的数据库连接
    pool.end(); // 关闭连接池,也就是pool不可以getConnection()
  });
})

以上两种方式都能连接到数据库进行操作,那么两种方式那种好呢?小号问你是不是有很多朋友?个人觉得这应该是取决于你的需求,在高并发的情况下肯定是用连接池的方式会效率高点,但如果你没有高并发需求,其实普通连接和连接池连接没有太大的区别。(但我习惯连接池一把梭,问题不大,嘿嘿~)

然后根据官方对连接池的说法:数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。

个人理解:连接池就像一个缓存区,在用户请求比较多的时候,频繁的建立、关闭连接,肯定是比较浪费性能的,所有用个缓存区来过渡这样子。

参数说明

参数说明
host主机地址,如果是服务器环境一般是服务器IP (默认:localhost)
user数据库用户名
password数据库密码
port端口号 (默认:3306)
database数据库名
connectTimeout连接超时(单位:毫秒)
charset连接字符集(默认:'UTF8_GENERAL_CI',注意字符集的字母都要大写)
localAddress此IP用于TCP连接(可选)
socketPath连接到unix域路径,当使用 host 和 port 时会被忽略
timezone时区(默认:'local')
stringifyObjects是否序列化对象
typeCast是否将列值转化为本地JavaScript类型值 (默认:true)
queryFormat自定义query语句格式化方法
supportBigNumbers数据库支持bigint或decimal类型列时,需要设此option为true (默认:false)
bigNumberStringssupportBigNumbers和bigNumberStrings启用 强制bigint或decimal列以JavaScript字符串类型返回(默认:false)
dateStrings强制timestamp,datetime,data类型以字符串类型返回,而不是JavaScript Date类型(默认:false)
debug开启调试(默认:false)
multipleStatements是否许一个query中有多个MySQL语句 (默认:false)
flags用于修改连接标志
ssl使用ssl参数(与crypto.createCredenitals参数格式一至)或一个包含ssl配置文件名称的字符串,目前只捆绑Amazon RDS的配置文件

更多参数说明:传送门

简单封装

创建 mysql.js 文件,内容如下:

const mysql = require('mysql');
const pool = mysql.createPool({
  host: 'localhost',
  user: 'root',
  password: '12345',
  database: 'test',
  multipleStatements: true,
  connectionLimit: 10
});

let query = (sql, values) => {
  return new Promise((resolve, reject) => {
    pool.getConnection((err, connection) => {
      if(err) {
        reject(err);
      }else {
        connection.query(sql, values, (err, rows) => {
          if(err) {
            reject(err);
          }else {
            resolve(rows);
          }
          connection.release();
        })
      }
    })
  });
};

module.exports = {
  query
};

创建 test_sql.js 文件,内容如下:

sql相关的分离出单独文件,因为有一些sql很复杂,全搞一起很难管理。

const {query} = require('./mysql');

exports.getUserList = options => {
  let sql = `select * from user`;
  return query(sql)
};

exports.addUser = options => {
  let sql = `insert into user set username=?,age=?`;
  return query(sql, options)
};

exports.updateUser = options => {
  let sql = `update user set username='${options.username}' where id=${options.id}`;
  return query(sql)
};

exports.deleteUser = id => {
  let sql = `delete from user where id=${id}`;
  return query(sql)
};

主业务文件 test.js,内容如下:

const test_sql = require('./test_sql');
/*
// 增
test_sql.addUser(['YD', 18]).then(res => {
  console.log(res)
})
// 改
test_sql.updateUser({username: 'yd', id: 2}).then(res => {
  console.log(res)
})
// 删
test_sql.deleteUser(2).then(res => {
  console.log(res)
})
*/

// 查
test_sql.getUserList().then(res => {
  console.log(res)
})

最后附上截图一张:

好了,大致就写到这里了。。。

个人感觉自己文笔不是很好,是个比较偏实践类的人,但偶尔也羡慕那些写文写得好的大佬,也想学学大佬们写些有趣的东西。所谓的菜鸟的自我修养,就是向大佬的看齐,即使当作学习的笔记也罢,反正就是把自己知道的东西说出来而已,这是我一个写文的念头。同时也我希望自己是个能以最简洁的言语讲清一个事要点的人,所谓读书在精不在多怎么一个方式和大家见面。