Nodejs oracledb詳細解讀


node 連接 oracledb 代碼模塊。

具體配置連接數據庫方式,請看oracledb原文地址:https://www.npmjs.com/package/oracledb

windows的環境搭建:https://www.cnblogs.com/caiyt/p/10129710.html,Linux也需要配置,Linux的配置具體百度一下,網上很多。

gctx.js

//gctx.js
/**
 * global context
 * @type {{}}
 */
let gctx = {
    /**
     * 普通程序日志
     */
    ERROR_CODE_RUN: '0',
    /**
     * 接口調用報錯
     */
    ERROR_CODE_API: '1',
    /**
     * 數據庫執行報錯(其實這個也算程序錯誤...)
     */
    ERROR_CODE_DB: '2',
    /**
     * 程序錯誤
     */
    ERROR_CODE_SYS: '3',
};
/**
 * 全局封裝的錯誤異常
 * @param msg 問題描述
 * @param code 問題代碼
 * @param param 導致問題的入參數據
 * @returns {Error}{
 *     code//自定義錯誤編碼
 *     message//消息
 *     file//具體錯誤位置
 * }
 */
gctx.error = function (msg, code, param = null) {
    let error = (new Error);
    error.param = param;
    error.code = common.isEmpty(code) ? gctx.ERROR_CODE_SYS : code;
    error.message = msg;
    error.file = error.stack.split('\n')[2];
    return error;
};
/**
 * 通用解析異常,並提取錯誤位置
 * @param e
 * @returns {string}
 */
gctx.parse = function (e) {
    if (typeof (e) == "string") {
        e = new Error(e);
    }
    if (e.code === undefined) {
        e.code = gctx.ERROR_CODE_SYS;
    }
    let pos = null;
    if (e.file === undefined) {
        pos = e.stack.split('\n')[2];
        e.file = pos;
    } else {
        pos = e.file;
    }
    e.msg = `錯誤提示:${e.message};`;
    e.message = `${e.message}報錯位置:${pos}`;
    return e;
}
module.exports = gctx;

  common.js

//文件模塊
let fs = require('fs');
//文件解碼模塊
let iconv = require('iconv-lite');
//json long精度問題處理
var JSONstrict = require('json-bigint')({"storeAsString": true});

let common = {};

module.exports = common;


/************************************************通用功能輔助方法*********************************************************/

/**
 * @description 判斷是否非空
 * @param obj
 * @param checkObj 是否檢查空對象
 * @returns {boolean}
 */
common.isNotEmpty = function (obj, checkObj = false) {
    if (obj === 0)//0需要特殊處理
    {
        return true;
    }
    if (checkObj) {
        if (typeof (obj) == 'object' && obj !== null) {
            //避免數組類對象
            if (obj.constructor.name == 'Array') {
                return obj.length != 0;
            }
            return (Object.keys(obj).length != 0);
        }
        if (Array.isArray(obj)) {
            return obj.length != 0;
        }
    }
    if (obj == null || obj == "null" || obj === "" || typeof (obj) == undefined || typeof (obj) == "undefined" || obj == "undefined" || typeof (obj) == null || typeof (obj) == "null") {
        return false;
    } else {
        return true;
    }
}
/**
 * @description 判斷是否為空
 * @param obj
 * @param checkObj 是否檢查空對象
 * @returns {boolean}
 */
common.isEmpty = function (obj, checkObj = false) {
    return !common.isNotEmpty(obj, checkObj);
}


/**
 * 替換對象屬性的值,當值為空的時候,賦值空字符串
 * */
common.replace_object_value = function (obj) {
    let keys = Object.keys(obj);
    for (let i = 0; i < keys.length; i++) {
        if (common.isNotEmpty(obj[keys[i]]) == false) {
            obj[keys[i]] = "";
        }
    }
}

/**刪除數組中的某一個對象
 _arr:數組
 _obj:需刪除的對象
 */
common.removeArray = function (_arr, _obj) {
    let length = _arr.length;
    for (let i = 0; i < length; i++) {
        if (_arr[i] === _obj) {
            if (i === 0) {
                _arr.shift(); //刪除並返回數組的第一個元素
                return _arr;
            } else if (i === length - 1) {
                _arr.pop();  //刪除並返回數組的最后一個元素
                return _arr;
            } else {
                _arr.splice(i, 1); //刪除下標為i的元素
                return _arr;
            }
        }
    }
}

/**
 * 刪除對象空屬性
 * */
common.removeObjectEmptyProperty = function (obj) {
    //遍歷對象屬性
    for (let key in obj) {
        if (common.isNotEmpty(obj[key]) == false) {
            delete obj[key];//刪除空值的屬性
        }
    }
}

/**************************************特殊字符處理模塊*******************************************************************/


/**
 * 計算分頁
 * total_count 總條數
 * pageSize 每頁條數
 * 返回總頁數
 * */
common.CountPage = function (total_count, pageSize) {
    total_count = parseInt(total_count);
    pageSize = parseInt(pageSize);
    return parseInt((total_count + pageSize - 1) / pageSize);
}

//獲取六位隨機數
common.r6 = function () {
    return Math.random() * 900000 | 0 + 100000;
}

//獲取n位隨機數,隨機來源chars
common.GetRandom = function (n) {
    let chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
    let res = "";
    for (let i = 0; i < n; i++) {
        let id = Math.ceil(Math.random() * (chars.length - 1));
        res += chars[id];
    }
    return res;
}

/*獲取請求客戶的IP地址*/
common.IP = function (req) {
    let ipAddress;
    let headers = req.headers;
    let forwardedIpsStr = headers['x-real-ip'] || headers['x-forwarded-for'];
    forwardedIpsStr ? ipAddress = forwardedIpsStr : ipAddress = null;
    if (!ipAddress) {
        ipAddress = req.connection.remoteAddress;
    }
    return ipAddress;
}

//判斷json對象是否存在屬性字段
common.isEmptyObject = function (item) {
    if (Object.keys(item).length == 0) {
        return true;
    }
    return false;
}

//判斷json對象是否存在屬性字段
common.isNotEmptyObject = function (item) {
    return !common.isEmptyObject(item);
}

/************************************************JSON功能輔助方法*********************************************************/
//把對象轉化成字符串
common.JSON_stringify = function (data) {
    // typeof   2                   輸出 number
    // typeof   null                輸出 object
    // typeof   {}                  輸出 object
    // typeof    []                 輸出 object
    // typeof   (function(){})      輸出 function
    // typeof    undefined          輸出 undefined
    // typeof   '222'               輸出 string
    // typeof  true                 輸出 boolean
    if (typeof data != "string") {
        return JSON.stringify(data);
    }
    return data;
}
//把字符串轉化成對象
common.JSON_parse = function (data) {
    try {
        if (typeof data == "string") {
            if (common.isNotEmpty(data) && common.stringHelper.isJSON(data)) {
                return JSONstrict.parse(data);
            }
            return data;
        } else {
            return data;
        }
    } catch (err) {
        throw err;//拋出異常
    }
}

//JSON對象轉化成數據
common.JSONToArray = function (data) {
    let keys = Object.keys(data);
    let array = [];
    for (let i = 0; i < keys.length; i++) {
        let id = keys[i];
        array.push({id: id, name: data[id]});
    }
    array.sort((a, b) => a.id - b.id);//升序排序
    return array;
}

//輸出字符串
common.consoleLog = function () {
        let position = (new Error).stack.split("\n")[2].trim();
        let time = (new Date).toTimeString();
        console.log("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
        console.log(`時間:${time};位置:${position};`);
        console.log(...arguments);
        console.log("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
    
}


//輸出字符串
common.consoleTitleLog = function (title, text) {
        var position = (new Error).stack.split("\n")[2].trim();
        var time = (new Date).toTimeString();
        console.log("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
        console.log(`時間:${time};位置:${position};`);
        console.log(title, text);
        console.log("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
    
}

/**
 * 將true轉化成1,false轉化成0,原因為了適應oracle與mssql
 * */
common.booleanToChar = function (value) {
    if (value == true || value == "true") {
        return 1;
    } else {
        return 0;
    }
}

/**
 * 將true轉化成1,false轉化成0,原因為了適應oracle與mssql
 * */
common.charToBoolean = function (value) {
    if (value == true || value == "true" || value == "1") {
        return true;
    } else {
        return false;
    }
}
/************************************************時間功能輔助方法*********************************************************/
//獲取當前時間轉日期字符串
common.nowtimeToDateStr = function () {
    let now = new Date();
    let year = now.getFullYear(), month = now.getMonth() + 1, day = now.getDate();
    if (month < 10) {
        month = "0" + month;
    }
    if (day < 10) {
        day = "0" + day;
    }
    let datestr = year + "" + month + "" + day;
    return datestr;
}

//獲取當前時間轉日期字符串
common.nowtimeToDatetimeStr = function () {
    let now = new Date();
    let year = now.getFullYear(),
        month = now.getMonth() + 1,
        day = now.getDate(),
        hour = now.getHours(),
        minute = now.getMinutes(),
        second = now.getSeconds();
    if (month < 10) {
        month = "0" + month;
    }
    if (day < 10) {
        day = "0" + day;
    }
    if (hour < 10) {
        hour = "0" + hour;
    }
    if (minute < 10) {
        minute = "0" + minute;
    }
    if (second < 10) {
        second = "0" + second;
    }

    let datetimestr = year + "" + month + "" + day + "" + hour + "" + minute + "" + second;
    return datetimestr;
}

//獲取當前時間轉日期字符串
common.nowtimeToDatetime = function () {
    let now = new Date();
    let year = now.getFullYear(),
        month = now.getMonth() + 1,
        day = now.getDate(),
        hour = now.getHours(),
        minute = now.getMinutes(),
        second = now.getSeconds();
    if (month < 10) {
        month = "0" + month;
    }
    if (day < 10) {
        day = "0" + day;
    }
    if (hour < 10) {
        hour = "0" + hour;
    }
    if (minute < 10) {
        minute = "0" + minute;
    }
    if (second < 10) {
        second = "0" + second;
    }

    let datetimestr = year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;
    return datetimestr;
}

/**
 * 將Date對象轉化成字符串
 * time 時間字符串
 * format 輸出時間格式
 * */
common.formatTime = function (time, format) {
    let t = new Date(time);
    let tf = function (i) {
        return (i < 10 ? '0' : '') + i
    };
    return format.replace(/yyyy|MM|dd|HH|mm|ss|S/g, function (a) {
        switch (a) {
            case 'yyyy':
                return tf(t.getFullYear());
                break;
            case 'MM':
                return tf(t.getMonth() + 1);
                break;
            case 'mm':
                return tf(t.getMinutes());
                break;
            case 'dd':
                return tf(t.getDate());
                break;
            case 'HH':
                return tf(t.getHours());
                break;
            case 'ss':
                return tf(t.getSeconds());
                break;
            case "S":
                return tf(t.getMilliseconds());
                break;
        }
    })
}

// 對Date的擴展,將 Date 轉化為指定格式的String
// 月(M)、日(d)、小時(H)、分(m)、秒(s)、季度(q) 可以用 1-2 個占位符,
// 年(y)可以用 1-4 個占位符,毫秒(S)只能用 1 個占位符(是 1-3 位的數字)
// 例子:
// (new Date()).Format("yyyy-MM-dd HH:mm:ss.S") ==> 2006-07-02 08:09:04.423
// (new Date()).Format("yyyy-M-d HH:m:s.S")      ==> 2006-7-2 8:9:4.18
Date.prototype.Format = function (fmt) { //author: meizz
    let o = {
        "M+": this.getMonth() + 1,                 //月份
        "d+": this.getDate(),                    //日
        "H+": this.getHours(),                   //小時
        "m+": this.getMinutes(),                 //分
        "s+": this.getSeconds(),                 //秒
        "q+": Math.floor((this.getMonth() + 3) / 3), //季度
        "S": this.getMilliseconds()             //毫秒
    };
    if (/(y+)/.test(fmt))
        fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
    for (let k in o)
        if (new RegExp("(" + k + ")").test(fmt))
            fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
    return fmt;
}

/**
 * 時間戳轉為時間
 * timestamp 時間戳
 * format 時間格式 yyyy-MM-dd HH:mm:ss
 * */
common.GetTime = function (timestamp, format) {
    if (common.isNotEmpty(timestamp) && timestamp != 0) {
        let date = new Date(timestamp * 1000);    //根據時間戳生成的時間對象
        return common.formatTime(date, format);
    } else {
        return "";
    }
}

/**
 * DateTime時間格式轉換為Unix時間戳格式
 * date 時間字符串
 * */
common.GetTimeStamp = function (date) {
    return parseInt(new Date(date).getTime() / 1000);
}

/**
 * 兩個時間段的間隔
 * 間隔天數 interval的值為1000*60*60*24
 * 間隔分鍾數 interval的值為1000*60
 * @param startDate 開始時間字符串
 * @param endDate 時間字符串
 * @param interval 間隔時間
 * @returns {number}
 * @constructor
 */
common.GetDateDiff = function (startDate, endDate, interval) {
    let startTime = new Date(Date.parse(startDate.replace(/-/g, "/"))).getTime();//獲取毫秒數
    let endTime = new Date(Date.parse(endDate.replace(/-/g, "/"))).getTime();//獲取毫秒數
    let time = parseInt(Math.abs((startTime - endTime)) / interval);
    return time;
}
/**
 * 比較時間大小,返回bool類型
 * startDate 開始時間
 * endDate 結束時間
 * */
common.CompareDate = function (startDate, endDate) {
    return new Date(startDate) < new Date(endDate)
}

/************************************************Cookie功能輔助方法*********************************************************/
//cookie轉化
common.codeCookie = function (str) {
    let strRtn = "";
    for (let i = str.length - 1; i >= 0; i--) {
        strRtn += str.charCodeAt(i);
        if (i) strRtn += "a";
    }
    return strRtn;
}


//cookie反轉化
common.decodeCookie = function (str) {
    let strArr;
    let strRtn = "";
    strArr = str.split("a");
    for (let i = strArr.length - 1; i >= 0; i--)
        strRtn += String.fromCharCode(eval(strArr[i]));
    return strRtn;
}

/*************************************數據庫輔助方法******************************************************************/
//替換對象
common.replaceObject = function (item) {
    let str = common.JSON_stringify(item);
    str = str.replace(/'/g, "");
    return common.JSON_parse(str);
}

//時間值轉化為Oracle時間格式
common.replaceOracleTimeStr = function (text, format) {
    if (common.isNotEmpty(text))
        return "to_date('" + text + "','" + format + "')";
    return null;
}

/**
 * 時間條件語句
 * jkpt_isOra 數據庫是否為oracle數據庫
 * field 時間字段名稱
 * condition >= 或者<=
 * time 值
 * format js時間格式化yyyy-MM-dd HH:mm:ss
 * oracleFormat oracle時間格式化寫法:yyyy-mm-dd hh24:mi:ss
 * */
common.returnTimeConditionSQL = function (jkpt_isOra, field, condition, time, format, oracleFormat) {
    let where = "";
    //判斷是否有時間值
    if (common.isNotEmpty(time)) {
        if (jkpt_isOra) {
            where = " and " + field + condition + " to_date('" + common.formatTime(time, format) + "','" + oracleFormat + "')";
        } else {
            where = " and " + field + condition + " '" + common.formatTime(time, format) + "'";
        }
    }
    return where;
}



/**
 * 當前時間修改語句
 * jkpt_isOra 數據庫是否為oracle數據庫
 * field 時間字段名稱
 * */
common.returnInsertTimeSQL = function (jkpt_isOra) {
    let where = "";
    //判斷是否有時間值
    if (jkpt_isOra) {
        where = "sysdate ";
    } else {
        where = "getDate() ";
    }
    return where;
}

/**
 * 返回時間執行語句
 * jkpt_isOra 數據庫是否為oracle數據庫
 * time 值
 * format js時間格式化yyyy-MM-dd HH:mm:ss
 * oracleFormat oracle時間格式化寫法:yyyy-mm-dd hh24:mi:ss
 * */
common.returnTimeExecSQL = function (jkpt_isOra, time, format, oracleFormat) {
    let sql = null;
    //判斷是否有時間值
    if (common.isNotEmpty(time)) {
        if (jkpt_isOra) {
            sql = " to_date('" + common.formatTime(time, format) + "','" + oracleFormat + "')";
        } else {
            sql = " '" + common.formatTime(time, format) + "'";
        }
    }
    return sql;
}

/**
 * 數組數據轉化成查詢語句 IN () 的數據
 * list 數組字符串
 * */
common.returnListExecINSQL = function (list) {
    list = common.JSON_parse(list);
    if (list.length == 0) {
        return "";
    }
    let list_str = ""; //訂單字符串
    //遍歷訂單編號
    for (let i = 0; i < list.length; i++) {
        let id = list[i];
        if (common.isNotEmpty(id)) {
            list_str += "'" + list[i] + "',";
        }
    }
    list_str = list_str.substr(0, list_str.length - 1);
    return list_str;
}

/**
 * 讀取數據的時候,時間相差8個小時的處理,oracle的時間無需做處理,mssql的時間需要做處理
 * jkpt_isOra 數據庫是否為oracle數據庫
 * time 時間字段名稱
 * format js時間格式化yyyy-MM-dd HH:mm:ss
 * */
common.returnTimeFromDBSelect = function (jkpt_isOra, time, format) {
    //判斷是否為oracle,是的話替換時間不同的處理方式
    if (jkpt_isOra) {
        return common.formatTime(time, format);
    } else {
        //數據庫中獲取的數據轉換成json格式后,JS再取出來轉換成時間,發現小時數多了8,原因和當地時區有關系,
        // 解決辦法形如:0001-01-01T00:00:00 可以用replace替換掉T。
        let tempTime = common.JSON_stringify(time).replace("Z", "").replace("T", " ");
        // common.consoleLog("CREATETIME:"+time);
        // common.consoleLog("ReplaceCREATETIME:"+tempTime);
        return common.formatTime(tempTime, "yyyy-MM-dd HH:mm:ss");
    }
}


/*******************************************************************************************************/


/****************************************類型功能擴展**********************************************************/
/**
 * 為string類型新增方法
 * @returns {String}
 */
String.prototype.signMix = function () {
    if (arguments.length === 0) return this;
    let param = arguments[0], str = this;
    if (typeof (param) === 'object') {
        for (let key in param) {
            let value = param[key];
            value = value.toString().replace('$', '');
            str = str.replace(new RegExp("\\{:" + key + "\\}", "g"), value);
            //判斷值是否等null是的話,直接給null
            if (!(value === null)) {
                value = "N'" + value + "'";
            }
            str = str.replace(new RegExp("\\{" + key + "\\}", "g"), value);
        }
        return str;
    } else {
        for (let i = 0; i < arguments.length; i++) {
            // common.consoleLog (i+":"+ arguments[i]);
            str = str.replace(new RegExp("\\{" + i + "\\}", "g"), arguments[i]);
        }
        return str;
    }
}
String.prototype.trim = function () {
    return this.replace(/^\s+|\s+$/g, '');
};

/**
 * JSON對象中字符串的屬性值拼接成字符串
 * @param split_str 分隔符
 * @returns {string}
 */
common.objectJoin = function (obj, split_str) {
    let str = "";
    for (let key in obj) {
        if (typeof obj[key] == "string") {
            str += obj[key] + split_str;
        }
    }
    if (str != "")
        str = str.substr(0, str.length - 1)
    return str;
}


/****************************************文件讀寫功能**********************************************************/
//分割線
common.partition = "\r\n====================================================================================\r\n";
//結束分割線
common.endPartition = "\r\n***************************************************************************************\r\n";
/*******************保存日志***************************/
common.writeLog = async function (apiName, data) {
    try {
        let t = new Date();
        let days = t.Format("yyyyMMdd");
        await common.fileHelper.mkdirs('log');
        fs.appendFileSync(`log/${apiName}_${days}_logs.txt`, `${data}${common.endPartition}`, function (err) {
            if (err) {
                console.error(err);
            }
        });
    } catch (err) {
        console.error(apiName, data, err);
    }
}

/*******************讀取整個JSON文件字符串***************************/
/*******************注意:文件的格式必須是UTF-8格式,可用txt文本做另存為UTF-8格式的文件***************************/
/*
* 讀取 json文件
* file  文件的路徑
* */
common.readFile = function readFile(file) {
    //默認不用轉碼,默認是utf8的編碼
    // common.consoleLog (file)
    let fileStr = fs.readFileSync(file, {encoding: 'utf8'});
    if (fileStr == "")
        return "";
    // let buf = Buffer.from(fileStr,'utf8');
    // fileStr = iconv.decode(buf,'utf8');
    // common.consoleLog(fileStr);
    let str = common.JSON_parse(fileStr);
    // 獲取里面的key
    return str;
}


/*******************讀取文件Json對象的某個字段***************************/
/*
* 讀取 json文件  通過   key   獲取對應的value
* */
common.readFileBykey = function (file, key) {
    let str = common.readFile(file);
    // 獲取里面的key
    return str[key];
}

/*******************修改文件Json對象的某個字段***************************/

/**
 *   保存的字段
 *   file  文件路徑
 *   key  要修改的key
 *   value 要保存的值
 * */
common.writeFileBykey = function (file, key, value) {
    try {
        //默認不用轉碼,默認是utf8的編碼
        let fileStr = fs.readFileSync(file, {encoding: 'utf8'});
        // let buf = Buffer.from(fileStr, 'utf8');
        // let str = JSON.parse(iconv.decode(buf, 'utf8'));
        // common.consoleLog (str);
        // common.consoleLog("key:"+key +",value:"+value);
        let str = common.JSON_parse(fileStr);
        str[key] = value;
        common.consoleLog(str);
        fs.writeFileSync(file, common.JSON_stringify(str));  /// 寫入
        return true;
    } catch (err) {
        //寫入日志
        common.writeLog("writeFileBykey", file + err.message);
        return false;
    }
}

/**
 *   保存的Json對象
 *   file  文件路徑
 *   value 文件內容
 * */
common.writeFile = function (file, value) {
    try {
        //默認不用轉碼,默認是utf8的編碼
        // //寫入字符串轉化成utf8編碼,保證中文不會成亂碼
        // let buf = Buffer.from(value, 'utf8');
        // common.consoleLog(buf);
        // //字符串轉化一下編碼
        // value = iconv.decode(buf, 'utf8');
        // common.consoleLog(value);
        // let str = JSON.parse(value);
        fs.writeFileSync(file, common.JSON_stringify(value));  /// 寫入
        return common.returnResponse(true, "寫入數據成功。");
    } catch (err) {
        //寫入日志
        common.writeLog("writeFile", file + err.message);
        return common.returnResponse(false, err.message);
    }
}


//對創建文件夾函數進行改裝的函數隨意路徑沒文件夾會自動創建(格式: 'web/upImg/images/mytest/'+_y + '/'+ _m  + '/' + _d + "/")
common.MymkdirSync = function (url, mode, cb) {

    common.consoleLog("url" + url);

    let arr = url.split("/");

    mode = mode || '0755';

    cb = cb || function () {
    };

    if (arr[0] === ".") {//處理 ./aaa
        arr.shift();
    }

    if (arr[0] == "..") {//處理 ../ddd/d
        arr.splice(0, 2, arr[0] + "/" + arr[1])
    }

    function inner(cur) {
        if (!fs.existsSync(cur)) {//不存在就創建一個
            fs.mkdirSync(cur, mode);
        }

        if (arr.length) {
            inner(cur + "/" + arr.shift());
        } else {
            cb();
        }
    }

    arr.length && inner(arr.shift());
}

/**
 * 等待多少毫秒后,才能執行下面的代碼
 * 這種實現方式是利用一個偽死循環阻塞主線程。因為JS是單線程的。所以通過這種方式可以實現真正意義上的sleep()。
 * delay 毫秒時間
 * */
common.sleep = function (delay) {
    let start = (new Date()).getTime();
    while ((new Date()).getTime() - start < delay) {
        continue;
    }
}
common.isArray = (array) => {
    return Object.prototype.toString.call(array) === '[object Array]';
}

module.exports = common;

  

//導入oracledb模塊 //基於版本@3.0.1  安裝指令npm install oracledb
//node訪問oracleDB需要搭建訪問環境,否則無法正常訪問
//創建Oracle對象
let oracledb;


let config = null;
let common_config = null;

/**
* 初始化配置參數
*/
function init_config() {
if (config == null) {
common_config = require("./config");
config = require("./config").oracle_config;
}
}

/**
* 初始化數據庫對象
*/
function init() {
if (oracledb == null) {
try {
init_config();
//由於有些客戶不是oracle數據庫,由於oracle訪問需要搭建環境,所以需要是oracle數據庫才做模塊的新建,否則項目會出錯。
if (common_config.jkpt_isOra == 1) {
oracledb = require('oracledb');
//主要是這兩行,在oracledb的文檔中其實也有其它方法
//但是為了封裝方法,采用如下方法統一處理
oracledb.fetchAsBuffer = [oracledb.BLOB];
oracledb.fetchAsString = [oracledb.CLOB];
}
} catch (err) {
console.log("oracledb聲明錯誤原因:" + err.message);
}
}
}


let oracle = {};

//配置存儲過程是的輸出輸入,與參數類型
oracle.db = oracledb;

let connection = null;
oracle.connection = null;

async function initConnection() {
if (connection == null) {
init();
connection = await oracledb.getConnection(config);//配置默認連接池,配置過就無需再繼續配置
oracle.connection = connection;
common.consoleLog("初始化oracle數據庫連接");
}
}

/**
* 初始化連接參數
* @param {string} user 用戶名
* @param {string} password 密碼
* @param {string} connectString 數據庫連接字符串
*/
oracle.initConfig = async function (user, password, connectString) {
init_config();
if (user) {
config.user = user;
}
if (password) {
config.password = password;
}
if (connectString) {
config.connectString = connectString;
}
if (common.isEmpty(config.user) || common.isEmpty(config.password) || common.isEmpty(config.connectString)) {
throw gctx.error("oracle 連接參數為空!");
}
connection = null;
await initConnection();
}


//統計行號
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 (e) {
e = gctx.parse(e);
console.error(e);
return {state: false, data: e.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語句中的參數
* 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 }
};
* @param {JSON} isToJson boolean類型 每行都被提取為JavaScript對象 ,
*/
oracle.queryByParams = async function (sqlText, params, isToJson) {
try {
await initConnection();//初始化連接

let options = {outFormat: oracledb.ARRAY};
if (isToJson) {
options = {outFormat: oracledb.OBJECT};
}
let result = await connection.execute(sqlText, params, options);
return {state: true, data: result};//返回查詢的結果數據
} catch (e) {
console.error(e.message, sqlText);
e = gctx.parse(e);
await doReconnection(e.message, sqlText);
//判斷數據庫連接是否斷開
if (VerifyConnection(e.message)) {
let result = oracle.queryByParams(sqlText, params, isToJson);
return result;
}
return {state: false, data: e.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, sqlText);
//判斷數據庫連接是否斷開
if (VerifyConnection(err.message)) {
let result = oracle.executePro(sqlText, params);
return result;
}
return {state: false, data: err.message};//返回錯誤信息
}
};


/**
* 執行一條數據插入,修改,刪除,SQL語句(帶params參數)
* @param {string} sqlText 執行SQL語句
* "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();//初始化連接
// common.consoleLog(sqlText);
let result = await connection.execute(sqlText, params, {autoCommit: true});
return {state: true, data: result};//返回執行結果數據
} catch (err) {
common.consoleLog(err);
await doReconnection(err.message, sqlText);
//判斷數據庫連接是否斷開
if (VerifyConnection(err.message)) {
let result = oracle.execute(sqlText, params);
return result;
}
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 (e) {
e = gctx.parse(e);
await doReconnection(e.message, sqlText);
console.error(e);
//判斷數據庫連接是否斷開
if (VerifyConnection(e.message)) {
let result = oracle.executeMany(sqlText, params, options);
return result;
}
return {state: false, data: e.message};//返回錯誤信息
}
};


/**
* 驗證數據庫表是否存在
* tableName 表名
* 返回boolean類型,true或者false
* */
oracle.verifyHaveTable = async function (tableName) {
let select_sql = "select * from user_tables where table_name =upper('" + tableName + "')";
let result = await oracle.queryByParams(select_sql, [], true);
if (result.state) {
if (result.data.rows.length > 0) {
return true;
}
}
return false;
}

/**
* 驗證數據庫視圖是否存在
* tableName 視圖名稱
* 返回boolean類型,true或者false
* */
oracle.verifyHaveViewTable = async function (tableName) {
let select_sql = "select * from user_views where VIEW_NAME =upper('" + tableName + "')";
let result = await oracle.queryByParams(select_sql, [], true)
if (result.state) {
if (result.data.rows.length > 0) {
return true;
}
}
return false;
}

//執行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, sqlText) {
let time = new Date().Format("HH:mm:ss");
common.writeLog("oracle_connection", time + common.partition + sqlText + common.partition + message);
console.error(message);
//釋放連接,重新連接oracle
if (VerifyConnection(message)) {
connection = null;//重新初始化oracle連接
await initConnection();//初始化連接
}
}

//關閉結果集在關閉數據庫連接
async function doClose(connection, resultSet) {
try {
if (resultSet) {
await resultSet.close();//釋放讀取流
}
if (connection) {
await connection.close();//釋放連接,將連接放回池中
}
} catch (err) {
console.error(err.message);
}
}

/**
* @description 驗證數據庫連接是否正常
* @param message
* @return {boolean}
* @constructor
*/
function VerifyConnection(message) {
// common.consoleLog("VerifyConnection:" + message);//輸出錯誤信息
// console.error(message);
//釋放連接,重新連接mssql
if (message.search("not connected to ORACLE") >= 0
|| message.search("invalid connection") >= 0
|| message.search("connection lost contact") >= 0
|| message.search("通信通道的文件結尾") >= 0
|| message.search("未連接到 ORACLE") >= 0) {
return true;
}
return false;
}

module.exports = oracle;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM