代码地址:https://github.com/changeclass/Node_Blog.git
# 操作数据库
# 创建
创建数据库为了方便操作,我们使用可视化工具进行操作。可视化工具使用 Navicat Premium
。
鼠标右键选择新建数据库
数据库名为
myblog
其他默认即可。接下来开始建表。
users 表
blogs 表
在使用数据库操作时,首先要选择数据库即 use 数据库名
。例如我们的数据库叫 myblog
,那么输入的命令即
use myblog
# 增
insert into users (username,`password`,realname) values("张三","123","张三");
对
password
使用反引号的目的是:因为 password 是关键字,如果不加反引号,则会当作系统关键字处理。语法
insert into users (键1,键2,...) values(值1,值2,...);
# 改
条件修改
update users set realname='李四2' where username='lisi';
如果遇到安全问题,那么可尝试设置安全模式。
SET SQL_SAFE_UPDATES=0;
如果不添加后边的条件,那么会修改全部记录
# 删
条件删除
delete from users where username='lisi';
与修改类似,如果不添加条件,那么会删除整个表。
出于数据的宝贵,建议不要真的删除数据,而是使用一个标识表示数据是否生效。当删除时实际执行的是更新操作。
# 查
标准查询
select * from users where username='zhangsan' and `password`='123';
其语法如下:
select 键1,键2, from 表 where 条件1 and 条件2;
如果全部键则可以用
*
代替。where 后接查询条件,and 表示并,or 表示或。模糊查询使用 like 关键字。
select * from users where password like '%1%';
表示查询字段中包含 1 的记录。
排序
排序使用关键字
order by
。默认为升序,desc
表示降序select * from users where password like '%1%' order by id desc;
# 通过 NodeJs 操作 MySQL—— 基础
const mysql = require('mysql') | |
// 创建连接对象 | |
const con = mysql.createConnection({ | |
host:'localhost', // 主机 本地可使用 localhost | |
user:'root', // 数据库用户名 | |
password:'root', // 数据库用户的密码 | |
port:'3306', // 数据库端口号,默认 3306 | |
database:'myblog' // 需要连接的数据库 | |
}) | |
// 开始连接 | |
con.connect() | |
// 定义查询语句 | |
const sql = 'select * from users;' | |
// 创建查询对象 | |
con.query(sql,(err,result)=>{ | |
if(err){ | |
console.error(err) | |
return | |
} | |
console.log(result) | |
// 返回一个列表,其元素是 RowDataPacket 对象 | |
}) | |
// 关闭连接 | |
con.end() |
安装并导入
mysql
对象创建连接对象
const con = mysql.createConnection({
host:'localhost', // 主机 本地可使用 localhost
user:'root', // 数据库用户名
password:'root', // 数据库用户的密码
port:'3306', // 数据库端口号,默认 3306
database:'myblog' // 需要连接的数据库
})
连接并定义 sql 语句
// 开始连接
con.connect()
// 定义查询语句
const sql = 'select * from users;'
开始查询
// 创建查询对象
con.query(sql,(err,result)=>{
if(err){
console.error(err)
return
}
console.log(result)
// 返回一个列表,其元素是 RowDataPacket 对象
})
关闭连接
// 关闭连接
con.end()
# 查询
当使用查询语句时,返回结果是一个列表,其元素是 RowDataPacket 对象。
# 修改
当修改时也返回一个对象,通过 changedRows
可以判断修改成功的行数。
# 新增
与修改返回的类似。
# NodeJs 连接 MySQL 做成工具
封装成工具的原因很简单,为了更简单的使用查询语句。当查询时,只需要调用一个方法即可完成。而不需要每次查询都需要建立连接。
为了区分生成环境和开发环境,我们需要对两个环境配置不同的 MySQL 连接配置。
在 src 目录下新建一个文件夹写入 db.js
用于定义不同环境下的 MySQL 配置。
const env = process.env.NODE_ENV // 环境信息 | |
let MYSQL_CONF | |
if (env === 'dev') { | |
MYSQL_CONF = { | |
host: 'localhost', // 主机 本地可使用 localhost | |
user: 'root', // 数据库用户名 | |
password: 'root', // 数据库用户的密码 | |
port: '3306', // 数据库端口号,默认 3306 | |
database: 'myblog' // 需要连接的数据库 | |
} | |
} | |
if (env === 'production') { | |
MYSQL_CONF = { | |
host: 'localhost', // 主机 本地可使用 localhost | |
user: 'root', // 数据库用户名 | |
password: 'root', // 数据库用户的密码 | |
port: '3306', // 数据库端口号,默认 3306 | |
database: 'myblog' // 需要连接的数据库 | |
} | |
} | |
module.exports = {MYSQL_CONF} |
由于测试,所以开发环境与生产环境的配置是一样的。
接下来只需要创建连接时使用 MYSQL_CONF
即可。
同样的在 src 目录下创建一个 db 的文件夹,用于存放一些关于数据库操作的逻辑。
const mysql = require('mysql') | |
const {MYSQL_CONF} = require('../conf/db') | |
// 创建连接对象 | |
const con = mysql.createConnection(MYSQL_CONF) | |
// 开始连接 | |
con.connect() | |
// 统一执行 sql 的函数 | |
function exec(sql) { | |
return new Promise(((resolve, reject) => { | |
con.query(sql, (err, result) => { | |
if (err) { | |
console.error(err) | |
reject(err) | |
return | |
} | |
resolve(result) | |
// 返回一个列表,其元素是 RowDataPacket 对象 | |
}) | |
})) | |
} | |
module.exports = { | |
exec | |
} |
MySQL 是异步操作,为了简化,将其封装成一个 promise 对象。
# 修改:获取文章列表
由于将获取数据的方法封装成了 promise 对象,那么在路由处获取数据时应修改为如下:
const result = getList(author, keyword) | |
return result.then(listData => { | |
return new SuccessModel(listData) | |
}) |
路由获取到数据后同样的返回一个 promise 对象,所以 app.js
处也需要修改。
// 处理 Blog 路由 | |
const blogResult = handleBlogRouter(req, res) | |
if (blogResult) { | |
blogResult.then(blogData => { | |
res.end(JSON.stringify(blogData)) | |
}) | |
return | |
} |
# 修改:获取博客详情与新建博客
获取博客详情接口比较简单,
// 博客详情 | |
const getDetail = (id) => { | |
const sql = `select * from blogs where id=${id};` | |
return exec(sql).then(rows => { | |
// 将数组变成对象格式即返回元素第一项 | |
return rows[0] | |
}) | |
} |
路由处做出同样的处理
if (method === 'GET' && req.path === '/api/blog/detail') { | |
const result = getDetail(id) | |
return result.then(data => { | |
return new SuccessModel(data) | |
}) | |
} |
新建博客时,返回的数据为插入的 ID,当插入数据后,MySQL 会返回一个对象,其中 insertId
表示当前插入的 ID,将其返回即可。
const newBlog = (blogData = {}) => { | |
const title = blogData.title | |
const content = blogData.content | |
const author = blogData.author | |
const createTime = Date.now() | |
const sql = `insert into blogs (title,content,createtime,author) values('${title}','${content}',${createTime},'${author}');` | |
return exec(sql).then(insertData => { | |
return { | |
id: insertData.insertId | |
} | |
}) | |
} |
由于没有完成登陆接口,因此登陆后才会有的作者信息需要使用假数据。
if (method === 'POST' && req.path === '/api/blog/new') { | |
req.body.author = 'zhangsan' // 登陆后改为真实数据 | |
const result = newBlog(req.body) | |
return result.then(data => { | |
return new SuccessModel(data) | |
}) | |
} |
# 修改:博客更新与删除
更新博客与新建类似,但只需要修改标题和内容即可。
// 更新博客 | |
const updataBlog = (id, blogData = {}) => { | |
//id 为更新博客的 ID | |
const title = blogData.title | |
const content = blogData.content | |
const sql = `update blogs set title='${title}',content='${content}' where id=${id};` | |
return exec(sql).then(updateData=>{ | |
return updateData.affectedRows > 0; | |
}) | |
} |
删除博客为真删除,而不是加删除(出于学习目的)。需要进行双重验证,防止删除他人的博文。
// 删除博客 | |
const delBlog = (id, author) => { | |
const sql = `delete from blogs where id='${id}' and author='${author}'` | |
//id 就是要删除博客的 ID | |
return exec(sql).then(deleteData => { | |
return deleteData.affectedRows > 0; | |
}) | |
} |
路由处修改与上面的几种方法类似。
// 更新一篇博客 | |
if (method === 'POST' && req.path === '/api/blog/update') { | |
const result = updataBlog(id, req.body) | |
return result.then(val => { | |
if (val) { | |
return new SuccessModel(val) | |
} else { | |
return new ErrorModel('更新博客失败') | |
} | |
}) | |
} | |
// 删除一篇博客 | |
if (method === 'POST' && req.path === '/api/blog/del') { | |
const author = 'zhangsan' | |
const result = delBlog(id, author) | |
return result.then(val => { | |
if (val) { | |
return new SuccessModel() | |
} else { | |
return new ErrorModel("删除失败") | |
} | |
}) | |
} |
# 修改:登陆接口
登陆成功后返回其用户名与真实姓名,密码是不需要返回的。
const {exec} = require('../db/mysql') | |
const loginCheck = (username,password)=>{ | |
const sql = `select username,realname from users where username='${username}' and password='${password}';` | |
return exec(sql).then(rows=>{ | |
return rows[0] || {} | |
}) | |
} |
获取完数据后路由处也只需要简单的修改即可。
// 登陆 | |
if (method === 'POST' && req.path === '/api/user/login') { | |
const {username, password} = req.body | |
const result = loginCheck(username, password) | |
return result.then(data => { | |
if (data.username) { | |
return new SuccessModel("登陆成功") | |
} else { | |
return new ErrorModel("登陆失败") | |
} | |
}) | |
} |
最后只需要将 app.js
处修改即可。
// 处理 User 路由 | |
const userResult = handleUserRouter(req, res) | |
if (userResult) { | |
userResult.then(userData => { | |
res.end(JSON.stringify(userData)) | |
}) | |
return | |
} |
与 Blog 逻辑相似。