Node.js (四)– 分别连接MongoDB与MySQL数据库,实现增删查改功能

一、Node.js 访问MongoDB 数据库

MongoDB 对许多平台都提供驱动可以访问数据库,如C#、Java、Node.js等。

1.1、安装MongoDB访问驱动

命令如下:

全局安装驱动:npm install mongodb -g
?
在当前项目中引入:npm install mongodb --save

1.2、连接数据库

const { MongoClient } = require("mongodb");  //导入依赖对象mongo客户端
?
let url="mongodb://127.0.0.1:27017";  //数据库连接字符串
?
let client=new MongoClient(url);  //实例化一个mongo客户端
?
async function run(){
    try{
        await client.connect();  //连接
        await client.db("nfit").command({ping:1});  //向数据库nfit发送命令
        console.log("连接数据库成功!");
    }
    finally{
        await client.close();
    }
}
?
run().catch(console.log);

1.3、添加数据

const { MongoClient } = require("mongodb");  //依赖MongoClient

let client=new MongoClient("mongodb://127.0.0.1:27017");  //实例化一个客户端

async function run(){
    try{
        let db=await client.db("nfit");  //获取数据库
        let students=await db.collection("students");  //获取集合,表
        let doc={id:202201,name:"tom",age:19};  //将添加的数据对象
        let result=await students.insertOne(doc);  //执行向数据库中添加数据并等待响应结果
        console.log(result);
    }
    finally{
        await client.close();  //关闭数据库
    }
}

run().catch(console.log);

1.4、添加多条数据

const { MongoClient } = require("mongodb");  //依赖MongoClient

let client=new MongoClient("mongodb://127.0.0.1:27017");  //实例化一个客户端

async function run(){
    try{
        let db=await client.db("nfit");  //获取数据库
        let students=await db.collection("students");  //获取集合,表
        let docs=[{id:202202,name:"rose",age:17},{id:202203,name:"mark",age:18}];  //将添加的数据对象
        let result=await students.insertMany(docs);  //执行向数据库中添加数据并等待响应结果
        console.log(result);
    }
    finally{
        await client.close();  //关闭数据库
    }
}

run().catch(console.log);

1.5、修改数据

const { MongoClient } = require("mongodb");
let client=new MongoClient("mongodb://127.0.0.1:27017");

async function run(){
    try{
        let db=await client.db("nfit"); //获取数据库
        let students=await db.collection("students");  //获取集合
        let filter={id:202201};  //要更新的数据的过滤条件
        let result=await students.updateOne(filter,{$set:{name:"汤姆"}});  //执行更新单条数据
        console.log(result);
    }
    finally{
        await client.close();  //关闭
    }
}

run().catch(console.log);

1.6、查询数据

1.6.1、查询单条记录
const { MongoClient } = require("mongodb");
let client=new MongoClient("mongodb://127.0.0.1:27017");
?
async function run(){
    try{
        let db=await client.db("nfit"); //获取数据库
        let students=await db.collection("students");  //获取集合
?
        let filter={id:202201};  //过滤条件
        let obj=await students.findOne(filter);  //根据过滤条件查找单条数据
        console.log(obj);
    }
    finally{
        await client.close();  //关闭
    }
}
?
run().catch(console.log);
1.6.2、查询多条记录
const { MongoClient } = require("mongodb");
let client=new MongoClient("mongodb://127.0.0.1:27017");
?
async function run(){
    try{
        let db=await client.db("nfit"); //获取数据库
        let students=await db.collection("students");  //获取集合
?
        let query={id:{$gte:202201}};  //查询条件是id大于等于202201
        let cursor=await students.find(query);  //执行查询并返回游标对象
?
        let result=[];  //学生数组,返回包装用
?
        await cursor.forEach(data=>result.push(data));  //遍历游标,取出数据
?
        console.log(result);
    }
    finally{
        await client.close();  //关闭
    }
}
?
run().catch(console.log);

1.7、删除数据

const { MongoClient } = require("mongodb");
let client=new MongoClient("mongodb://127.0.0.1:27017");

async function run(){
    try{
        let db=await client.db("nfit"); //获取数据库
        let students=await db.collection("students");  //获取集合
        let filter={id:202201};  //要删除的数据的过滤条件
        let result= await students.deleteOne(filter);  //执行删除
        console.log(result);
    }
    finally{
        await client.close();  //关闭
    }
}

run().catch(console.log);

1.8、连接MongoDB数据库,实现curd、图片上传(使用element-ui框架)功能的完整代码如下:

路由 Api 接口:

// 导入模块
var express = require('express');
var router = express.Router();
var _ = require("lodash");
var path = require("path");
var multer = require('multer');

// 图片上传
// 文件上传的内置方法
var imgName = ""; // 这个是保存在路径里的名称
const storage = multer.diskStorage({
    // 文件存储路径
    destination(req, file, callback) {
        // 上传的图片放到本地的文件夹里面
        let imgUrl = "E:/qd/11. node.js/练习/test05_mongoDB/public/images"
        // 回调函数
        callback(null, imgUrl)
    },
    filename(req, file, callback) {
        // 后缀名,到时候添加数据的时候,先把它设为空,然后进入图片上传页,然后做修改的操作
        imgName = _.random(0, 9999999999999) + path.extname(file.originalname);
        callback(null, imgName); // 把生成的名称放在这里

    }
});

// 也是内置函数
const addfild = multer({
    storage
});

// 连接数据库
const {
    MongoClient,
    ObjectId
} = require("mongodb");

let url = "mongodb://127.0.0.1:27017";

let client = new MongoClient(url);

// 传参数:需要的数据,i(如果它为1,就查询,2就添加...),res:返回给客户端的数据
async function run(bookDate, i, res, req) {
    try {
        await client.connect();
        let db = await client.db("book"); // 连接数据库的
        let book = db.collection("bookInfo"); // 连接集合的
        let result = ""; // SQL语句
        // 执行哪个执行语句    
        if (i == 1) {
            result = await book.find().toArray(); // 查询所有数据的
        }
        if (i == 2) {
            // 获取图书编号
            let id = parseInt(req.params.id);
            // 查看id是什么类型的
            console.log(typeof id);
            // 执行语句
            result = await book.deleteOne({
                id: id
            });
        }
        if (i == 3) {
            // 获取通过post请求传递过来的参数
            let inputText = req.body;
            // 获取编号最大的图书,实现编号自动增长
            let maxObj = await (book.find().sort({_id:-1}).limit(1)).toArray();
            // 获取id和图片名称,把id 和 图片名称存进数据库里面
            inputText.id = parseInt(maxObj[0].id) + 1;
            inputText.picture = imgName;

            // // 执行语句
            result = await book.insertOne(inputText);

            console.log(inputText);
            console.log(maxObj);
            console.log(inputText.id);
        }
        if (i == 4) {
            console.log(parseInt(req.params.id));
            result = await book.find({
                id: parseInt(req.params.id)
            }).toArray();
            console.log(result);

        }
        if (i == 5) {
            let inputText = req.body;

            result = await book.updateOne({id:inputText.id}, {$set: {name: inputText.name,picture: imgName,author: inputText.author,price: inputText.price}});
            console.log(result);
        }

        // 返回客户端的信息
        res.json({
            status: "成功!",
            data: result
        });

    } finally {
        // 通常写关闭数据库的,但是,目前还不需要,因为只能查询一次,之后就关闭了!
        // await client.close();
    }
}

// 查询所有数据
router.get("/", (req, res, next) => {
    // 调用run 方法,传参数
    run("", 1, res, req);
});

// 删除
router.delete("/:id", (req, res, next) => {
    run("", 2, res, req);
});

// 上传图片的
// 在这里传内置函数过去
router.post("/file", addfild.single('file'), (req, res, next) => {

})

// 添加
router.post("/", (req, res, next) => {
    run("", 3, res, req);
})

// 渲染数据
router.get("/:id", (req, res, next) => {
    run("", 4, res, req);
})

// 修改数据
router.put("/", (req, res, next) => {
    run("", 5, res, req);
})



module.exports = router;

ejs 页面:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="stylesheets/book.css">
    <link rel="stylesheet" href="stylesheets/index.css">
</head>

<body>
    <div id="app">
        <h3>图书管理系统</h3>
        <div id="addbtn">
            <!-- <div id="sort">
                <button id="sortId" @click="sortId">按id倒序</button>
            </div>
            <div id="search">
                <input type="text" name="" id="searchText">
                <button id="searchbtn" @click="search">搜索</button>
            </div> -->
            <button id="appBook">新增图书&nbsp;+&nbsp;</button>
        </div>
        <table>
            <tr>
                <th>编号</th>
                <th>书名</th>
                <th>封面</th>
                <th>作者</th>
                <th>价格</th>
                <th>操作</th>
            </tr>
            <tr v-for="(b, i) in book" :key="b.id">
                <td>{{ b.id }}</td>
                <td>{{ b.name }}</td>
                <td>
                    <div id="picture" :style="{backgroundImage: 'url(/images/' + b.picture + ')'}"></div>
                </td>
                <td>{{ b.author }}</td>
                <td>{{ b.price }}</td>
                <td>
                    <button id="update" @click="edit(b.id)">编辑</button>
                    <button id="delete" @click="del(b.id)">删除</button>
                </td>
            </tr>
        </table>

        <!-- 模态框 -->
        <div id="modal_box">
            <!--修改or添加  -->
            <div id="mdinfo">
                <table>
                    <tr>
                        <td colspan="2" id="td">新增图书信息</td>
                    </tr>
                    <tr>
                        <td>书名:</td>
                        <td>
                            <input type="text" id="name" class="text" v-model="bookObj.name" />
                        </td>
                    </tr>
                    <tr>
                        <td>作者:</td>
                        <td>
                            <input type="text" id="author" class="text" v-model="bookObj.author" />
                        </td>
                    </tr>
                    <tr>
                        <td>价格:</td>
                        <td>
                            <input type="text" id="price" class="text" v-model="bookObj.price" />
                        </td>
                    </tr>
                    <tr>
                        <td>封面:</td>
                        <td style="display: flex;">
                            <el-upload ref="mYupload" action="string" :http-request="handleChange"
                                list-type="picture-card" :on-preview="handlePictureCardPreview"
                                :on-remove="handleRemove" :on-change="handleChange">
                                <i class="el-icon-plus"></i>
                            </el-upload>
                            <el-dialog :visible.sync="dialogVisible">
                                <img width="100%" :src="dialogImageUrl" alt="">
                            </el-dialog>
                            <!-- <div class="Browse" :style="{backgroundImage: 'url(/images/' +  + ')'}"></div> -->
                        </td>
                    </tr>
                    <tr>
                        <td colspan="2">
                            <button id="btn1" class="btn" @click="save">提交</button>
                            <button id="btn2" class="btn" @click="cancel">取消</button>
                        </td>
                    </tr>
                </table>
            </div>
        </div>
    </div>
</body>
<script src="javascripts/jquery-1.12.4.js"></script>
<script src="javascripts/axios.js"></script>
<script src="javascripts/vue.js"></script>
<script src="javascripts/index.js"></script>
<script>
    var path = "http://127.0.0.1:8082/bookApi/";
    var app = new Vue({
        el: "#app",
        data: {
            book: [],
            bookObj: { "id": 0, "name": "", "picture": "", "author": "", "price": "" },
            // 文件上传
            dialogImageUrl: '',
            dialogVisible: false,
            rawName: ""
        },
        created() {
            // 查询所有的数据
            this.selectData();
            // 把图片的名称赋值
            this.bookObj.picture = this.rawName;
        },
        methods: {
            // 查询
            selectData() {
                axios
                    .get(path)
                    .then((res) => {
                        this.book = res.data.data;
                    })
            },
            // 删除
            del(id) {
                if (confirm("您确定要删除这数据吗?")) {
                    axios
                        .delete(path + id)
                        .then((res) => {
                            console.log(id);
                            console.log(res);
                            alert("删除成功!");
                            // 调用查询全部的数据
                            this.selectData();
                        })
                }
            },
            // 文件上传的样式
            // 删除
            handleRemove(file, fileList) { },
            // 放大
            handlePictureCardPreview(file) {
                this.dialogImageUrl = file.url;
                this.dialogVisible = true;
            },
            // 添加封面图
            handleChange(file) {
                // 如果缩略图这个元素在的话,就删除这个这个,然后重新上传一个(其实就是为了方便修改图片)
                if ($('.el-upload-list__item').length > 0) {
                    // 删除缩略图图片
                    $(".el-upload-list__item").remove();
                }
                let formDate = new FormData();
                formDate.append('file', file.raw);
                // console.log(file.raw.name);
                formDate.append("file", file);
                axios
                    .post(path + "file", formDate)
                    .then((data) => {
                    });
                this.rawName = file.raw.name;
            },
            // 添加图书与修改图书
            save() {
                if (this.bookObj.id) {
                    // 修改
                    axios
                        .put(path, this.bookObj)
                        .then((data) => {
                            if (data.data.status === "成功!") {
                                // console.log(data.data.data);
                                alert("修改成功!");
                                this.bookObj = { id: 0, name: "", picture: "", author: "", price: "" };
                                $("#modal_box").css("display", "none");
                                // 删除缩略图图片
                                $(".el-upload-list__item").remove();
                                //  重新查询一次数据
                                this.selectData();
                            }
                        })

                } else {
                    // 添加
                    axios
                        .post(path, this.bookObj)
                        .then((data) => {
                            if (data.data.status === "成功!") {
                                // console.log(data.data.data);
                                alert("添加成功!");
                                this.book.id = 0; // 因为是添加,所以id要重置为0
                                this.bookObj = { id: 0, name: "", picture: "", author: "", price: "" };
                                $("#modal_box").css("display", "none");
                                // 删除缩略图图片
                                $(".el-upload-list__item").remove();
                                //  重新查询一次数据
                                this.selectData();
                            }
                        })
                }
            },
            // 编辑图书
            edit(id) {
                $("#td").html("修改图书信息");
                $("#modal_box").slideToggle();
                axios
                    .get(path + id)
                    .then((data) => {
                        this.bookObj = data.data.data[0];
                        // 寻找ul节点,然后创建li节点,并给li节点添加一个类,最后把li添加到ul里面
                        var ul = document.querySelector('ul');
                        var li = document.createElement("li");
                        li.className = "el-upload-list__item";

                        // 再创建一个img节点
                        var img = document.createElement("img");
                        //设置 img 图片地址、宽、高
                        img.src = "images/" + this.bookObj.picture;
                        img.width = 148;
                        img.height = 148;

                        ul.appendChild(li);
                        li.appendChild(img);

                        // console.log(this.bookObj);
                    })
            },
            // 模态框取消按钮
            cancel() {
                $("#modal_box").css("display", "none");
                $(".text").val("");
                // 删除缩略图图片
                $(".el-upload-list__item").remove();
            }
        }
    });

    // 模态框显示
    $("#appBook").click(function () {
        $("#modal_box").slideToggle();
        $("#td").html("新增图书信息");
    });

</script>

</html>

运行结果:

img

二、Node.js 访问 MySQL 数据库

2.1、导入mysql模块

npm i mysql;

2.2、连接并查询

const mysql=require("mysql");  //依赖mysql模块

//创建连接池对象
let pool=mysql.createPool({
    host:"localhost",  //主机
    user:"root",  //用户名
    password:"123456",  //密码
    database:"gomall"  //数据库,port可以省去
});


pool.getConnection((connErr,conn)=>{  //获取连接对象
    pool.query("select id,name,sex from student",(err,results)=>{//执行查询
        if(err) throw err;  //如果有错误,则抛出异常
        console.log(JSON.parse(JSON.stringify(results)));  //转换并输出查询结果
        conn.release();  //释放连接
    });
});

2.3、带参数查询

const mysql=require("mysql");  //依赖mysql模块

//创建连接池对象
let pool=mysql.createPool({
    host:"localhost",  //主机
    user:"root",  //用户名
    password:"123456",  //密码
    database:"gomall"  //数据库,port可以省去
});


pool.getConnection((connErr,conn)=>{  //获取连接对象
    pool.query("select id,name,sex from student where sex=?",['boy'],(err,results)=>{//执行查询
        if(err) throw err;  //如果有错误,则抛出异常
        console.log(JSON.parse(JSON.stringify(results)));  //转换并输出查询结果
        conn.release();  //释放连接
    });
});

2.4、新增数据

const mysql=require("mysql");  //依赖mysql模块

//创建连接池对象
let pool=mysql.createPool({
    host:"localhost",  //主机
    user:"root",  //用户名
    password:"123456",  //密码
    database:"gomall"  //数据库,port可以省去
});

let sql="insert into student(name,sex) values(?,?)";
pool.getConnection((connErr,conn)=>{  //获取连接对象
    pool.query(sql,['tom','boy'],(err,results)=>{//执行添加,指定参数
        if(err) throw err;  //如果有错误,则抛出异常
        console.log(results);  //输出结果
        conn.release();  //释放连接
    });
});

2.5、便捷增加

const mysql=require("mysql");  //依赖mysql模块

//创建连接池对象
let pool=mysql.createPool({
    host:"localhost",  //主机
    user:"root",  //用户名
    password:"123456",  //密码
    database:"gomall"  //数据库,port可以省去
});

let sql="insert into student set ?";
let student={name:"rose",sex:"girl"};
pool.getConnection((connErr,conn)=>{  //获取连接对象
    pool.query(sql,student,(err,results)=>{//执行添加,指定参数对象
        if(err) throw err;  //如果有错误,则抛出异常
        console.log(results);  //输出结果
        conn.release();  //释放连接
        //process.exit(1);  //关闭应用
    });
});

2.6、更新数据

const mysql=require("mysql");  //依赖mysql模块

//创建连接池对象
let pool=mysql.createPool({
    host:"localhost",  //主机
    user:"root",  //用户名
    password:"123456",  //密码
    database:"gomall"  //数据库,port可以省去
});

let sql="update student set name=?,sex=? where id=?";
pool.getConnection((connErr,conn)=>{  //获取连接对象
    pool.query(sql,['mark','boy',34],(err,results)=>{//执行更新,指定参数
        if(err) throw err;  //如果有错误,则抛出异常
        console.log(results);  //输出结果
        conn.release();  //释放连接
    });
});

2.7、便捷更新数据

const mysql=require("mysql");  //依赖mysql模块

//创建连接池对象
let pool=mysql.createPool({
    host:"localhost",  //主机
    user:"root",  //用户名
    password:"123456",  //密码
    database:"gomall"  //数据库,port可以省去
});

let sql="update student set ? where id=?";
let student={name:"jone",sex:'boy'};
pool.getConnection((connErr,conn)=>{  //获取连接对象
    pool.query(sql,[student,33],(err,results)=>{//执行更新,指定参数
        if(err) throw err;  //如果有错误,则抛出异常
        console.log(results);  //输出结果
        conn.release();  //释放连接
    });
});

2.8、删除数据

const mysql=require("mysql");  //依赖mysql模块

//创建连接池对象
let pool=mysql.createPool({
    host:"localhost",  //主机
    user:"root",  //用户名
    password:"123456",  //密码
    database:"gomall"  //数据库,port可以省去
});

let sql="delete from student where id=?";
pool.getConnection((connErr,conn)=>{  //获取连接对象
    pool.query(sql,[33],(err,results)=>{//执行查询
        if(err) throw err;  //如果有错误,则抛出异常
        if(results.affectedRows===1){  //如果影响行数为1
            console.log("删除成功");
        }
        else{
            console.log("删除失败");
        }
        conn.release();  //释放连接
    });
});

2.9、释放连接

//查询
pool.getConnection((err,conn)=>{
    pool.query("select * from student",(err,results)=>{
        results=JSON.parse(JSON.stringify(results));
        results.forEach((stu,index)=>{
            console.log(stu.id,stu.name,stu.sex);
        });
        conn.release();
        process.exit(1);
    });
}); 

2.10、路由文件参考:

// 1.导入mysql模块
const mysql = require('mysql')

// 2.建立和MySQL数据库的联系
const db = mysql.createPool({
    host: '127.0.0.1', //数据库的ip地址
    user: 'root', //登录数据库的账号
    password: 'hoshi1234', //登录数据库的密码
    datebase: 'my_dv_01' //指定要操作那个数据库
})

// 3.测试mysql模块是否正常工作
db.query('select 1',(err, results) => {
    // mysql工作期间报错了
    if(err) return console.log(err.message);

    // 能够正常执行SQL语句
    console.log(results);
    // 返回 [ RowDataPacket { '1': 1 } ]
})


// 4.查询 users 表中所有数据
const sqlStr = 'select * from my_dv_01.users'
db.query(sqlStr ,(err, results) => {
    // mysql工作期间报错了
    if(err) return console.log(err.message);

    // 能够正常执行SQL语句
    console.log(results);
    // 返回 users表的字段
})


// 5.插入数据到 users 表中

// 要插入到表中的数据
const user = { usersname: 'benben', password:'886886' }

// 待执行的 SQL语句 ,英文问号 ? 代表占位符(SQL语法)
const sqlStr2 = 'insert into users (usersname, password) VALUES (?,?)'

// 使用数组的形式,依次为 ? 占位符指定具体的位置
db.query(sqlStr2, [user.usersname , user.password],(err, results) => {
        // mysql工作期间报错了
        if(err) return console.log(err.message);

        // 如果执行的是insert into这个插入语句,则results是一个对象
        // 可以通过results.affectedRows判断是否成功
        if(results.affectedRows === 1) {
            console.log('插入数据成功');
            // 打开MySQL的users表格也能看到新数据
            // 当前数据只有4条,本条数据id为什么是5?
            // 因为之前有过4的数据,但是被删除了,id具有唯一性,删除了也不能被其他数据使用
        }
})


// 插入数据的便捷方式
const user = { usersname: 'niuniu', password:'000000' }

// 定义待执行的 SQL 语句
const sqlStr = 'insert into my_dv_01.users set ?'

// 执行 SQL 语句
db.query(sqlStr, user,(err, results) => {
        
        if(err) return console.log(err.message);
        if(results.affectedRows === 1) {
            console.log('插入数据成功');
        }
})


// 如何更新用户的信息(UPDATE 语句用于更新表中已存在的记录)

// 要插入到表中的数据
const user = { id: 6, usersname: '犇犇', password:'000111' }

// 定义SQL语句
const sqlStr = 'update my_dv_01.users set usersname=?, password=? where id=?'

// 执行SQL语句
db.query(sqlStr,[user.usersname, user.password, user.id], (err, results) => {
    if(err) return console.log(err.message);
    if(results.affectedRows === 1) {
        console.log('插入数据成功');
    }
})

// 更新用户信息的便捷方式(数据对象的每个属性和字段一一对应的情况下可使用)
const user = { id: 6, usersname: '夸夸牛', password:'000111' }

// 定义SQL语句
const sqlStr = 'update my_dv_01.users set ? where id=?'

// 执行SQL语句
db.query(sqlStr,[user, user.id], (err, results) => {
    if(err) return console.log(err.message);
    if(results.affectedRows === 1) {
        console.log('插入数据成功');
    }
})


// 删除数据
// 定义SQL语句
const sqlStr = 'delete from my_dv_01.users where id=?'

// 执行SQL语句
// SQL语句中有多个占位符,则必须使用数组为每个占位符指定具体的值
// 如果只有一个占位符,则可以省略数组
db.query(sqlStr,5,(err,results) => {
    if(err) return console.log(err.message);
        if(results.affectedRows === 1) {
            console.log('删除数据成功');
        }
})


// 标记删除
// 使用delete语句会把数据真正删除掉,非常危险,一般情况下推荐使用标记删除,类似于修改status字段的状态,比如更新成1表示删除;

// 定义SQL语句
const sqlStr = 'update my_dv_01.users set status=? where id=?'

// 执行SQL语句
db.query(sqlStr,[1, 3],(err, results) => {
    if(err) return console.log(err.message);
            if(results.affectedRows === 1) {
                console.log('标记删除成功');
            }
})

2.11、封装代码

访问数据库的代码存在许多的重复,为了便于维护与扩展可以将数据库访问代码封装起来。

  • 创建一个 mysqlutil.js 文件,代码如下:

const mysql=require("mysql");  //依赖mysql模块
?
//创建连接池对象
let pool=mysql.createPool({
    host:"localhost",  //主机
    user:"root",  //用户名
    password:"123456",  //密码
    database:"bookInfo"  //数据库,port可以省去
});
?
function query(sql,param){
    return new Promise((resolve,reject)=>{
        pool.getConnection((connErr,conn)=>{  //获取连接对象
            pool.query(sql,param||[],(err,results)=>{//执行sql
                try{
                    if(err) reject(err);
                    resolve(JSON.parse(JSON.stringify(results)));
                }
                finally{
                    conn.release();  //释放连接
                }
            });
        });
    });
}
?
module.exports={query};

创建一个js文件,测试代码如下:

const mysqlutil=require("./mysqlutil");  //导入mysql工具模块
?
//查询所有
//mysqlutil.query("select * from student").then(console.log).catch(console.log);
//查询并带参数
//mysqlutil.query("select * from student where id=?",[1]).then(console.log).catch(console.log);
?
//执行更新
let sql="update student set ? where id=?";
let student={name:"张二",sex:"girl"};
//mysqlutil.query(sql,[student,1]).then(console.log).catch(console.log);
?
async function findAll(){
    try{
        let result= await mysqlutil.query("select * from student");
        return result;
        }
    catch(err){
        throw err;
    }
}
?
findAll().then(console.log);
2.12、连接MySQL数据库,实现curd、图片上传(使用element-ui框架)功能的完整代码如下:

封装代码 util 包:

const mysql=require("mysql");  //依赖mysql模块

//创建连接池对象
let pool=mysql.createPool({
    host:"localhost",  //主机
    user:"root",  //用户名
    password:"123456",  //密码
    database:"bookInfo"  //数据库,port可以省去
});

function query(sql,param){
    return new Promise((resolve,reject)=>{
        pool.getConnection((connErr,conn)=>{  //获取连接对象
            pool.query(sql,param||[],(err,results)=>{//执行sql
                try{
                    if(err) reject(err);
                    resolve(JSON.parse(JSON.stringify(results)));
                }
                finally{
                    conn.release();  //释放连接
                }
            });
        });
    });
}

module.exports={query};

路由 Api 接口:

const mysqlutil = require("./mysqlutil"); //导入mysql工具模块
var express = require("express");
var router = express.Router();

async function findAll(sql, param) {
    try {
        let result = await mysqlutil.query(sql, param);
        return result;
    } catch (err) {
        throw err;
    }
}

// 查询
router.get("/", (req, res) => {
    let sql = "select * from book";
    findAll(sql, "").then(result => {
        res.json({
            status: "ok",
            data: result
        });
    });
});

// 删除
router.delete("/:id", (req, res) => {
    let sql = "delete from book where id=?";
    findAll(sql, [req.params.id]).then(result => {
        console.log(result);
        res.json({
            status: "ok",
            data: result
        });
    });
});

// 添加
router.post("/", (req, res) => {
    let sql = "insert into book set ?";
    let inputTest = req.body;
    findAll(sql, inputTest).then(result => {
        res.json({
            status: "ok",
            data: result
        });
    });
});

// 显示信息
router.get("/:id", (req, res) => {
    let sql = "select * from book where id= ?";
    findAll(sql, [req.params.id]).then(result => {
        res.json({
            status: "ok",
            data: result
        });
    });

});

// 修改
router.put("/", (req, res) => {
    let sql = "update book set ? where id=?";
    let inputTest = req.body;
    findAll(sql, [inputTest, inputTest.id]).then(result => {
        res.json({
            status: "ok",
            data: result
        });
    });
});

module.exports = router;

ejs 页面:

<!DOCTYPE html>
<html lang="en">
?
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>连接MySQL实现增删查改 —— 图书管理系统</title>
    <!-- 图标 -->
    <!-- ejs里的图片路径直接不用管public !!! -->
    <link rel="shortcut icon" href="/images/taozi.svg" type="image/x-icon">
    <!-- 样式 -->
    <link rel="stylesheet" href="/stylesheets/book.css">
</head>
?
<body>
    <div id="app">
        <h3>图书管理系统</h3>
        <div id="addbtn">
            <button id="appBook">新增图书&nbsp;+&nbsp;</button>
        </div>
        <table>
            <tr>
                <th>编号</th>
                <th>书名</th>
                <th>封面</th>
                <th>作者</th>
                <th>价格</th>
                <th>操作</th>
            </tr>
            <tr v-for="(b, i) in book" :key="b.id">
                <td>{{ b.id }}</td>
                <td>{{ b.name }}</td>
                <td>
                    <div id="picture" :style="{backgroundImage: 'url(/images/' + b.picture + ')'}"></div>
                </td>
                <td>{{ b.author }}</td>
                <td>{{ b.price }}</td>
                <td>
                    <button id="update" @click="edit(b.id)">编辑</button>
                    <button id="delete" @click="del(b.id)">删除</button>
                </td>
            </tr>
        </table>
?
        <!-- 模态框 -->
        <div id="modal_box">
            <!--修改or添加  -->
            <div id="mdinfo">
                <table>
                    <tr>
                        <td colspan="2" id="td">新增图书信息</td>
                    </tr>
                    <tr>
                        <td>书名:</td>
                        <td>
                            <input type="text" id="name" class="text" v-model="bookObj.name" />
                        </td>
                    </tr>
                    <tr>
                        <td>作者:</td>
                        <td>
                            <input type="text" id="author" class="text" v-model="bookObj.author" />
                        </td>
                    </tr>
                    <tr>
                        <td>价格:</td>
                        <td>
                            <input type="text" id="price" class="text" v-model="bookObj.price" />
                        </td>
                    </tr>
                    <tr>
                        <td>封面名称:</td>
                        <td>
                            <input type="text" id="pictures" class="text" v-model="bookObj.picture" />
                        </td>
                    </tr>
                    <tr>
                        <td colspan="2">
                            <button id="btn1" @click="save" class="btn">提交</button>
                            <button id="btn2" class="btn">取消</button>
                        </td>
                    </tr>
                </table>
            </div>
        </div>
    </div>
</body>
<script src="javascripts/jquery-1.12.4.js"></script>
<script src="javascripts/axios.js"></script>
<script src="javascripts/vue.js"></script>
<script>
?
    var path = "http://127.0.0.1:8082/bookApi/";
    var app = new Vue({
        el: "#app",
        data: {
            book: [],
            bookObj: { id: 0, name: "", picture: "", author: "", price: "" },
            // 获取编号最大的图书。即最新添加的编号
            maxId: ""
        },
        created() {
            this.seleBook();
        },
        methods: {
            seleBook() {
                axios
                    .get(path)
                    .then((data) => {
                        this.book = data.data.data;
                        // console.log(data.data.data);
                    })
                    .catch((err) => {
                        throw err;
                    });
            },
            // 传该行对应的对象,和第几行的索引
            del(id) {
                if (confirm("您确定要删除这数据吗?")) {
                    axios
                        .delete(path + id)
                        .then((data) => {
                            alert("删除成功!");
                            this.seleBook();
                        })
                }
            },
            save() {
                if (this.bookObj.id) {
                    // 修改
                    axios
                        .put(path, this.bookObj)
                        .then((data) => {
                            if (data.data.status === "ok") {
                                alert("修改成功!");
                                this.book = data.data.data;
                                this.bookObj = { id: 0, name: "", picture: "", author: "", price: "" };
                                $("#modal_box").css("display", "none");
                                this.seleBook();
                            }
                        })
?
                } else {
                    console.log(this.bookObj);
                    // 添加
                    axios
                        .post(path, this.bookObj)
                        .then((data) => {
                            if (data.data.status === "ok") {
                                alert("添加成功!");
                                this.book.id = 0; // 因为是添加,所以id要重置为0
                                this.bookObj = { id: 0, name: "", picture: "", author: "", price: "" };
                                $("#modal_box").css("display", "none");
                                this.seleBook();
                            }
                        })
                }
            },
            // 显示数据到模态框
            edit(id) {
                $("#td").html("修改图书信息");
                $("#modal_box").slideToggle();
                axios
                    .get(path + id)
                    .then((data) => {
                        this.bookObj = data.data.data[0];
                    })
                    .catch((err) => {
                        throw err;
                    })
            },
            // 搜索
            search() {
                console.log($("#searchText").val());
                axios
                    .get(path + ($("#searchText").val()))
                    .then((data) => {
                        this.book = [data.data.data];
                        // console.log(this.book.id);
                        console.log(this.book);
                    })
                    .catch((err) => {
                        throw err;
                    })
            },
            // 按id倒序
            sortId() {
                axios
                    .get(path + "book/sort")
                    .then((data) => {
                        this.book = data.data.data;
                    })
                    .catch((err) => {
                        throw err;
                    })
            },
            // 文件上传的样式
            // 删除
            handleRemove(file) {
                console.log(file);
            },
            hold() {
                $("#modal_box").css("display", "none");
            }
        },
    });
?
    // 模态框显示
    $("#appBook").click(function () {
        $("#modal_box").slideToggle();
        $("#td").html("新增图书信息");
    });
    $("#btn2").click(function () {
        $("#modal_box").css("display", "none");
        $(".text").val("");
    });
?
</script>
?
</html>