//导入oracledb模块 //基于版本@3.0.1  安装指令npm install oracledb
//node访问oracleDB需要搭建访问环境,否则无法正常访问
//创建Oracle对象
let oracledb  = null;

//引用通用方法模块
let common = require("./commonHelper");

try{
    oracledb = require('oracledb');
}
catch (e) {
    console.log("oracledb声明错误原因:"+ e.message);
}

//引用配置参数模块
let configFile = require("./config");

//默认config对象
let config=configFile.oracle_config;

let oracle={};

//配置存储过程是的输出输入,与参数类型
oracle.db=oracledb;

let connection = null;
async function initConnection()
{
    if(connection == null)
    {
        connection = await oracledb.getConnection(config);//初始化数据库连接
    }
}
/**
 * 初始化连接参数
 * @param {string} user 用户名
 * @param {string} password 密码
 * @param {string} connectString 数据库连接字符串
 */
oracle.initConfig=function(user,password,connectString){
    config.user=user;
    config.password=password;
    config.connectString=connectString;
    connection = null;
}

//统计行号
let rowCount = 0;
/**
 * 执行sql文本(带params参数),由于要使用逐条读取所以只能通过回调返回数据
 * @param {string} sqlText 执行的sql语句
 * @param {JSON} params sql语句中的参数
 * @param {JSON} isToJson 每行都被提取为JavaScript对象
 * @param {function} func 回调函数 逐行读取数据返回
 */
oracle.queryWithParams= async function(sqlText,params,isToJson,func){
    try {
        let options = {resultSet: true, outFormat: oracledb.ARRAY};
        if (isToJson) {
            options = {resultSet: true, outFormat: oracledb.OBJECT};
        }
        //获取连接池内的连接
        oracledb.getConnection(config,
            function (err, connection) {
                //判断是否存在异常信息,是释放数据库连接与返回错误信息
                if (executeErr(err,connection,func)) {
                    return;
                }
                connection.execute(sqlText, params, options, async function (err, result) {
                    //判断是否存在异常信息,是释放数据库连接与返回错误信息
                    if (executeErr(err,connection,func)) {
                        return;
                    }
                    rowCount = 0;//初始化统计行号
                    fetchOneRowFromRS(connection, result.resultSet, func);
                })
            });
    }
    catch (err) {
        console.log(err)
        return {state:false,data:err.message};//返回错误信息
    }

};
//递归读取结果集的数据
function fetchOneRowFromRS(connection, resultSet,func) {
    resultSet.getRow( // get one row
        async function (err, row) {
            if (err) {
                console.error(err.message);
                await doClose(connection, resultSet); // 发生异常错误的时候关闭数据库连接
            } else if (!row) {               // 无数据的时候,关闭数据库连接
                await doClose(connection, resultSet);
            } else {
                rowCount++;
                common.consoleLog ("fetchOneRowFromRS(): row " + rowCount);
                common.consoleLog (row);
                func({state:true,data:row});//返回行数据
                fetchOneRowFromRS(connection, resultSet,func);
            }
        });
}

/**
 * 执行sql文本(带params参数)
 * @param {string} sqlText 执行的sql语句
 * @param {JSON} params sql语句中的参数
 * @param {JSON} isToJson 每行都被提取为JavaScript对象
 */
oracle.queryByParams=async function(sqlText,params,isToJson){
    try {
        let options = { outFormat: oracledb.ARRAY };
        if(isToJson)
        {
            options ={outFormat: oracledb.OBJECT };
        }
        await initConnection();//初始化连接
        let result = await connection.execute(sqlText,params,options);
        return {state:true,data:result};//返回查询的结果数据
    }
    catch (err) {
        await doReconnection(err.message);
        return {state:false,data:err.message};//返回错误信息
    }
};

/**
 * 执行存储过程文本(带params参数)
 * @param {string} sqlText 执行的存储过程
 * @param {JSON} params sql语句中的参数
 * let params = {
       p1:  'Chris', // Bind type is determined from the data.  Default direction is BIND_IN
       p2:  'Jones',
       ret:  { dir: oracledb.BIND_OUT, type: oracledb.STRING, maxSize: 40 }
    };
 * 查询结果的常量outFormat选项oracledb.ARRAY    4001   将每行作为列值数组获取,oracledb.OBJECT    4002   将每行作为对象获取
 */
oracle.executePro=async function(sqlText,params){
    try {
        await initConnection();//初始化连接
        let result = await connection.execute(sqlText,params,{outFormat: oracledb.ARRAY });
        return {state:true,data:result};//返回存储过程执行结果数据
    }catch (err) {
        await doReconnection(err.message);
        return {state:false,data:err.message};//返回错误信息
    }
};

/**
 * 执行一条数据插入,修改,删除,存储过程文本(带params参数)
 * @param {string} sqlText 执行的存储过程
 * "INSERT INTO test VALUES (:id, :nm)",
 * @param {JSON} params sql语句中的参数
 * 写法一:{ id : {val: 1 }, nm : {val: 'Chris'} }
 * 写法二:[1, 'Chris']
 */
oracle.execute=async function(sqlText,params){
    try {
        await initConnection();//初始化连接
        let result = await connection.execute(sqlText,params,{ autoCommit: true});
        return {state:true,data:result};//返回执行结果数据
    }catch (err) {
        await doReconnection(err.message);
        return {state:false,data:err.message};//返回错误信息
    }
};

/**
 * 执行多条数据插入,修改,删除,存储过程,文本(带params参数)
 * @param {string} sqlText 执行的存储过程
 * let sql = "INSERT INTO em_tab VALUES (:a, :b)";
 * @param {JSON} params sql语句中的参数
 * 写法一:let params = [
 { a: 1, b: "Test 1 (One)" },
 { a: 2, b: "Test 2 (Two)" },
 { a: 3, b: "Test 3 (Three)" },
 { a: 4 },
 { a: 5, b: "Test 5 (Five)" }
 ];
 * 写法二:let params = [
 [1, "Test 1 (One)"],
 [2, "Test 2 (Two)"],
 [3, "Test 3 (Three)"],
 [4, null],
 [5, "Test 5 (Five)"]
 ];
 * @param {JSON} options sql语句中的参数
 * 写法一: let options = {
    autoCommit: true,//必须有这个自动提交参数
    bindDefs:
    [ { type: oracledb.NUMBER },
      { type: oracledb.STRING, maxSize: 15 }
    ] };
 写法二:
 let options = {
    autoCommit: true,//必须有这个自动提交参数
    bindDefs: {
      a: { type: oracledb.NUMBER },
      b: { type: oracledb.STRING, maxSize: 15 }
    } };
 */
oracle.executeMany=async function(sqlText,params, options){
    options = Object.assign({},options,{autoCommit: true});//默认配置执行语句自动提交
    try {
        await initConnection();//初始化连接
        let result = await connection.executeMany(sqlText,params,options);
        return {state:true,data:result};//返回执行结果数据
    }catch (err) {
        await doReconnection(err.message);
        return {state:false,data:err.message};//返回错误信息
    }
};

//执行SQL语句错误回调函数释放数据库连接
function executeErr(err,connection,func) {
    if (err) {
        console.error(err.message);
        doRelease_async(connection);//释放数据库连接
        func({state:false,data:err.message});//返回错误信息
        return true;
    }
    return false;
}
//关闭当前数据库连接
oracle.doClose =async function () {
    if(connection)
    {
        try {
            await connection.close();
        }
        catch (err) {
            console.error(err.message);
        }
    }
}

//关闭数据库连接
function doRelease_async(connection) {
    if(connection)
    {
        connection.close(
            function(err) {
                if (err) { console.error(err.message); }
            });
    }
}

//重新连接数据库
async function doReconnection(message) {
    //释放连接,重新连接oracle
    if(message.search("not connected to ORACLE")>=0 || message.search("invalid connection")>=0)
    {
        connection = null;//重新初始化oracle连接
    }
}

//关闭结果集在关闭数据库连接
async function doClose(connection, resultSet) {
    try {
        if(resultSet)
        {
            await resultSet.close();//释放读取流
        }
        if(connection)
        {
            await connection.close();//释放连接,将连接放回池中
        }
    }
    catch (err) {
        console.error(err.message);
    }
}

module.exports=oracle;

Nodejs OracleDB详细解读的更多相关文章

  1. Nodejs MSSQL详细解读

    MSSQL 是Nodejs用于连接Microsoft SQL Server 的插件. 安装方法 npm install mssql 配置Config const config = { user: '. ...

  2. MemCache超详细解读

    MemCache是什么 MemCache是一个自由.源码开放.高性能.分布式的分布式内存对象缓存系统,用于动态Web应用以减轻数据库的负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高 ...

  3. MemCache超详细解读 图

    http://www.cnblogs.com/xrq730/p/4948707.html   MemCache是什么 MemCache是一个自由.源码开放.高性能.分布式的分布式内存对象缓存系统,用于 ...

  4. rpm软件包管理的详细解读

    CentOS系统上使用rpm命令管理程序包:安装.卸载.升级.查询.校验.数据库维护 1.基本安装 rpm -ivh PackageFile 2.rpm选项 rpm -ivh --test Packa ...

  5. MemCache详细解读

    MemCache是什么 MemCache是一个自由.源码开放.高性能.分布式的分布式内存对象缓存系统,用于动态Web应用以减轻数据库的负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高 ...

  6. Android BLE蓝牙详细解读

    代码地址如下:http://www.demodashi.com/demo/15062.html 随着物联网时代的到来,越来越多的智能硬件设备开始流行起来,比如智能手环.心率检测仪.以及各式各样的智能家 ...

  7. 为你详细解读HTTP请求头的具体含意

    当我们打开一个网页时,浏览器要向网站服务器发送一个HTTP请求头,然后网站服务器根据HTTP请求头的内容生成当次请求的内容发送给浏览器.你明白HTTP请求头的具体含意吗?下面一条条的为你详细解读,先看 ...

  8. 详细解读Volley(三)—— ImageLoader & NetworkImageView

    ImageLoader是一个加载网络图片的封装类,其内部还是由ImageRequest来实现的.但因为源码中没有提供磁盘缓存的设置,所以咱们还需要去源码中进行修改,让我们可以更加自如的设定是否进行磁盘 ...

  9. 【Python】【Web.py】详细解读Python的web.py框架下的application.py模块

    详细解读Python的web.py框架下的application.py模块   这篇文章主要介绍了Python的web.py框架下的application.py模块,作者深入分析了web.py的源码, ...

随机推荐

  1. 带着新人学springboot的应用12(springboot+Dubbo+Zookeeper 下)

    上半节已经下载好了Zookeeper,以及新建了两个应用provider和consumer,这一节我们就结合dubbo来测试一下分布式可不可以用. 现在就来简单用一下,注意:这里只是涉及最简单的部分, ...

  2. Chapter 4 Invitations——15

    He slouched off, back toward the school. 他无精打采的回去了学校. I heard a low chuckle. 我听到了低声的笑. Edward was wa ...

  3. spring框架应用系列二:component-scan自动扫描注册装配

    component-scan自动扫描注册装配 本文系作者原创,转载请注明出处:http://www.cnblogs.com/further-further-further/p/7717331.html ...

  4. 【深度学习与TensorFlow 2.0】卷积神经网络(CNN)

    注:在很长一段时间,MNIST数据集都是机器学习界很多分类算法的benchmark.初学深度学习,在这个数据集上训练一个有效的卷积神经网络就相当于学习编程的时候打印出一行“Hello World!”. ...

  5. Java线程创建形式 Thread构造详解 多线程中篇(五)

    Thread作为线程的抽象,Thread的实例用于描述线程,对线程的操纵,就是对Thread实例对象的管理与控制. 创建一个线程这个问题,也就转换为如何构造一个正确的Thread对象. 构造方法列表 ...

  6. Windows已遇到关键问题,将在一分钟后自动重新启动,请立即保存工作

    Windows已遇到关键问题,将在一分钟后自动重新启动,请立即保存工作 1. 把电脑右下角网络断开 2.同时按 "WIN+R" 打开“运行”命令窗口 输入“cmd”命令,按回车键“ ...

  7. selinux基本

    TE模型 主体划分为若干组,称为域 客体划分为若干组,每个组称为一个类型   DDT(Domain Definition Table,域定义表,二维),表示域和类型的对应访问权限,权限包括读写执行 一 ...

  8. Flask的请求处理机制

    在Flask的官方文档中是这样介绍Flask的: 对于Web应用,与客户端发送给服务器的数据交互至关重要.在Flask中由全局的request对象来提供这些信息 属性介绍 request.method ...

  9. 《C#并发编程经典实例》学习笔记—2.3 报告任务

    问题 异步操作时,需要展示该操作的进度 解决方案 IProgress<T> Interface和Progress<T> Class 插一段话:读<C#并发编程经典实例&g ...

  10. 【默认加入持久化机制,防止消息丢失,v0.0.3】对RabbitMQ.Client进行一下小小的包装,绝对实用方便

    RabbitMQ是一个老牌的非微软的消息队列组件,一般来说应该能满足中小型公司对消息队列生产的需求,平时我们在.NET开发环境下运用它是可能会需要RabbitMQ.Client的SDK库,此库是官网提 ...