node.js 数据库操作工具类封装

半城伤御伤魂 提交于 2019-12-07 06:27:50

背景

node.js 操作数据库的用法,目前只了解 mysql 和 oracledb 两个模块,它们的用法稍有不同。相比 oracledb,node.js 的 mysql 模块相对容易些,本文将整理 node.js 操作这两种数据库的通用方法,完成简单 SQL 语句的执行。

此外,node.js 操作数据库的过程跟 Java 的 JDBC 也有很大差异:ode.js 的数据库模块通过回调函数来处理数据库,可以在回调函数处理 results 之前关闭 connection 。而 Java 的 JDBC 操作数据库则需逐步从 Connection 到 ResultSet 顺次执行,如果未处理 ResultSet 就关闭 Connection 就会报异常。

基本用法

简略分析了下源码,发现 oracledb 和 mysql 的连接池对象提供的 getConnection 实现方式有所差异。

mysql 连接池的 getConnection 只能通过回掉函数完成对连接对象的处理,而且没有返回值,其源码为:
在这里插入图片描述

oracledb 连接池的 getConnection 可以返回一个包裹了 connection 的 Promise 对象,所以它支持 await 操作;同时它也支持与 mysql 一样的回调函数的处理方式。

其大致流程为:
(1)oracledb 的 getConnection 无参方法:
在这里插入图片描述
(2)getConnection 最终由nodbUtil 工具的 promisify 实现:
在这里插入图片描述
(3)promisify 返回了一个 Promise 对象:
在这里插入图片描述
另一种接受一个回调函数的 getConnection 的源码基本跟 mysql 的一致。

数据库操作封装

基于连接池的数据库操作,从 getConnection 的 API 实现来看,我总结出两种处理数据库操作结果的方式。

第一种,上层调用者传递回调函数 dbCallback,在数据库连接的回调函数中再调用该dbCallback 完成对操作结果的处理。

以 oracledb 为例,封装 execute 方法如下:

    /**
     *   数据库执行操作:外界提供回调函数,用于对查询结果进行处理
     *   1、数据库连接的 execute 操作是一个异步请求,需要一个回掉函数
     *   2、如果等待异步完成,则需要使用 await 后则可调用回调函数
     *   3、外部调用者提供对数据的处理函数,然后在该数据库操作函数中调用回调函数。
     */
     async function oracleExecuteByCallback(oracledb, sql,params,dbCallback) {
         //回调函数参数封装对象
        var resultData = {
            status:0 //默认为失败状态
        };

        let connection;
        try {
            // Get a connection from the default pool
            connection = await oracledb.getConnection();

            //execute返回的是一个Promise对象
            let results = await connection.execute(sql, params);

            //成功:则记录操作结果
            resultData.status = 1;
            resultData.message = "操作成功";
            resultData.data = results;
            resultData.number = results.length;
        } catch (err) {
            //失败:记录失败信息
            resultData.message = "连接数据库失败";
            console.error(err);
        } finally {
            //关闭连接池
            if (connection) {
                try {
                    // Put the connection back in the pool
                    await connection.close();
                } catch (err) {
                    console.error(err);
                }
            }

            //统一执行回调
            dbCallback(resultData);
        }
    };

第二种,整个数据库操作返回一个包裹了操作结果的 Promise 对象,由上层调用者去对操作结果进行处理,此时的关键在于数据库连接和执行回调函数中返回 Promise 的resolve 数据,demo 如下:

    /**
     *   数据库执行操作:异步返回方式
     *   1、数据库连接的execute操作是一个异步请求,需要一个回调函数。
     *   2、封装一个Promise对象,在getConnection的回调中处理查询结果,封装resolve返回对象。
     *   3、外部调用者完成后续对resolve的对象的处理。
     */
    function oracleExecuteByPromise(db, sql,params) {
        return new Promise(async (resolve, reject) => {
            try{
                //数据库连接获取操作,需要传入一个回调函数,处理创建的连接。
                db.getConnection(function(err, connection) {
                    if(err) {
                        console.error(err);
                        reject({
                            status: 0,
                            message: '连接数据库失败'
                        });
                        return;
                    }

                    //数据库SQL执行操作,需要传入一个回调函数,处理执行结果。
                    let _query = connection.execute(sql, params, function(err, results) {
                        if(err) {
                            console.error(err);
                            reject({
                                status: 0,
                                message:'操作失败'
                            });
                            return;
                        }

                        //释放连接
                        connection.release();

                        //返回操作执行成功的结果
                        resolve({
                            status: 1,
                            data: results,
                            number: results.length,
                            message:'操作成功'
                        });
                    })
                })
            }catch(err){
                console.error(err);
                reject({
                    status: 0,
                    message:'操作异常'
                });
            }
        });
    }

mysql 的封装过程与上述类似,只是 mysql 不支持 await 操作,其回调函数方式和Promise 方式都只能在数据库连接回调中处理。实现过程已经上传本人的 Github 仓库了,这里不再赘述,有兴趣的朋友可以看看。

地址为:https://github.com/woodvine/nodeJsCommonUtil/blob/master/oracledbUtil.js

参考资料

https://segmentfault.com/a/1190000007535316?utm_source=tag-newest
这篇文章将 async 和 await 解释的笔记清晰,用作参考。

oracledb 的官方资料,example 中有很多例子。
https://github.com/oracle/node-oracledb/

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!