【node.js】node连接oracle——oracledb

oracledb为Oracle官方提供的node连接Oracle的第三方包,github:https://github.com/oracle/node-oracledb,oracle-api:https://oracle.github.io/node-oracledb/doc/api.html

一、安装oracledb

yarn add oracledb
cnpm/npm i oracledb -D

二、使用oracledb

首先需要引入oracledb

const oracledb = require('oracledb')

定义数据库用户名、密码、地址等信息

const DB_CONFIG = {
  user: '123', 
  password: '123',
  connectString: '127.0.0.1:1521/orcl' // 数据库地址:{IP:PORT/数据库名称}
}

开始连接数据库,其中可通过连接池或直接进行连接,下面是两种方式的具体实现:

// 使用连接池
async function run() {
  let pool;
  try {
    pool = await oracledb.createPool(DB_CONFIG);
    let connection;
    try {
      connection = await pool.getConnection();
      result = await connection.execute(`SELECT * FROM SYS_USER`);
    } catch (err) {
      throw (err);
    } finally {
      if (connection) {
        try {
          await connection.close(); 
        } catch (err) {
          throw (err);
        }
      }
    }
  } catch (err) {
    throw err;
  } finally {
    await pool.close();
  }
}
// 直接连接
async function run() {
  let connection;
    try {
      connection = await pool.getConnection(DB_CONFIG);
      result = await connection.execute(`SELECT * FROM SYS_USER`);
    } catch (err) {
      throw (err);
    } finally {
      if (connection) {
        try {
          await connection.close(); 
        } catch (err) {
          throw (err);
        }
      }
    }
}
run()

  其中connection.execute(sql,params,options)是用来执行sql的方法,它可以接受三个参数sql,params,optionssql是需要执行的sql语句,params用来设置sql中一些绑定属性或是返回值,options控制执行的sql的可选参数,如autoCommit是否自动提交事务。

2.1params

  params中的常用属性有dir,maxArraySize,maxSize,type,val

描述
dir绑定的方向,可选值:oracledb.BIND_IN,oracledb.BIND_INOUT,oracledb.BIND_OUToracledb.BIND_IN:作为变量输入;oracledb.BIND_OUT:作为变量输出。默认oracledb.BIND_IN
type数据在oracle中的数据类型:oracledb.STRING,oracledb.NUMBER,oracledb.CLOB,oracledb.BLOB,oracledb.DATE等等
val绑定变量的值

例:

const result = await connection.execute(
	`SELECT * FROM SYS_USER WHERE USER_AGE = :0 and USER_NAME = :1`,
	[12, '李四']
)
const result = await connection.execute(
	`SELECT * FROM SYS_USER WHERE USER_AGE = :age and USER_NAME = :name`,
	{
		name: {dir: oracledb.BIND_IN, val: '李四', type: oracledb.NUMBER}
		age: 12
	}
)
// 模糊查询无法使用:
const result = await connection.execute(
	`SELECT * FROM SYS_USER WHERE USER_NAME like '%:name%'`, //报错
	{name: '李四'}
)
// 可使用以下方式代替或使用instr代替like,注意使用instr第二个参数如果为’‘是查不到数据的
const result = await connection.execute(
	`SELECT * FROM SYS_USER WHERE USER_NAME like '%${name}%'`
)
// instr
const result = await connection.execute(
	`SELECT * FROM SYS_USER WHERE INSTR(USER_ANME, :name)>0`,
	{name: '李'}
)

2.2 options

options常用属性:

属性描述
autoCommit: Boolean自动提交事务
bindDefs: Object对象定义绑定变量的类型,大小和方向
dmlRowCounts: Boolean允许输出受每个输入数据记录影响的行数。只能为INSERT,UPDATE,DELETEMERGE语句设置为true
fetchInfo: Object定义如何在JavaScript中表示查询列数据的对象

fetchInfo使用示例:

const data = connection.execute(`select * from INTERFACE_IMMUTABLE`, null,
	{fetchInfo: {'INT_RESPONSE': { type : oracledb.STRING }}} // CLOB转成字符串
)

  关于connection.execute()返回的数据结构如下(metaData返回的为字段名,sql中可使用as替换,但返回的都是大写,rows是查询的数据):

{
    metaData: [
        {
            name: "ROLE_ID"
        },
        {
            name: "ROLE_NAME"
        }
    ],
    rows: [
        [
            10001,
            "管理员"
        ],
        [
            10002,
            "普通用户"
        ],
        [
            10003,
            "更新角色名"
        ]
    ]
}

三、封装oracledb工具类

const oracledb = require('oracledb')
const dateFormat = require('../util/date_format')

const DB_CONFIG = {
  user: '123', // 数据库用户名
  password: '123', // 数据库密码
  connectString: '127.0.0.1:1521/orcl' // 数据库地址:{IP:PORT/数据库名称}
}

var globalPool = null

class Oracle{
  /**
   * 创建连接池
   * @return {Promise<*>}
   */
  async createPool() {
    let pool;
    try {
      pool = await oracledb.createPool(DB_CONFIG);
      globalPool = pool;
    } catch(e) {
      globalPool = null
      throw e;
    }
    return pool;
  }
  
  /**
   * 创建连接
   * @return {Promise<void>}
   */
  async createConnection(pool) {
    let connection;
    try {
      connection = await pool.getConnection();
    } catch (e) {
      throw e;
    }
    return connection;
  }
  
  /**
   * 查询
   * @param sql
   * @param mapping
   * @param options
   * @return {Promise<void>}
   */
  query (sql, mapping, params = {}, options = {}) {
    return new Promise(async (resolve, reject) => {
      let pool;
      try {
        pool = await this.createPool();
        let connection;
        try {
          connection = await this.createConnection(pool);
          const result = await connection.execute(sql, params, options)
          // 转换mapping
          const keys = Object.keys(mapping)
          const values = Object.values(mapping)
          // map: {数据库列名:返回字段名}
          const map = values.reduce((pre, curr, index) => {
            pre.set(curr.name, {name: keys[index], type: values[index].type})
            return pre
          }, new Map())
          resolve(result.rows.map(item => result.metaData.reduce((pre, key, index) => {
            let value = map.get(key.name)
            let curr = item[index]
            // 类型转换
            if (value) {
              if (value.type === oracledb.DATE) {
                curr && (curr = dateFormat(curr))
              } else if (value.type === oracledb.NUMBER){
                curr && (curr = Number(curr))
              }
              // 无字段名与数据库对应
              if (value.name === undefined) {
                pre[key.name] = curr
              } else {
                pre[value.name] = curr
              }
            } else {  // 无字段名与数据库对应
              let {name} = key
              name = name.toLowerCase()
              // 下划线转驼峰
              name = name.replace(/\_(\w)/g, function(all, letter){
                return letter.toUpperCase()
              })
              pre[name] = curr
            }
            return pre
          }, {})));
        } catch (e) {
          throw e;
        } finally {
          if (connection) {
            try {
              await connection.close();
            } catch (e) {
              throw e
            }
          }
        }
      } catch (e) {
        reject(e);
        throw e;
      } finally {
        await pool.close();
      }
    });
  }
  
  /**
   * 插入操作
   * @param sql
   * @param params
   * @param options
   * @return {Promise<unknown>}
   */
  insert (sql, params = {}, options = {autoCommit: true}) {
    return new Promise(async (resolve, reject) => {
      let pool;
      try{
        pool = await this.createPool();
        let connection;
        try {
          connection = await this.createConnection(pool);
          const result = await connection.execute(sql, params, options);
          resolve(result);
        } catch (e) {
          throw e;
        } finally {
          if (connection) {
            try {
              await connection.close();
            } catch (e) {
              throw e;
            }
          }
        }
      } catch (e) {
        reject(e);
        throw e;
      } finally {
        await pool.close();
      }
    });
  }
  
  /**
   * 更新操作
   * @param sql
   * @param params
   * @param options
   * @return {Promise<unknown>}
   */
  update (sql, params = {}, options = {autoCommit: true}) {
   // ...同新增
  }
  
  /**
   * 删除操作
   * @param sql
   * @param params
   * @param options
   * @return {Promise<unknown>}
   */
  delete (sql, params = {}, options = {autoCommit: true}) {
    // ... 同新增
  }
  
  /**
   * 多sql事务控制
   * @param sqlParams [{sql, params, options, multi}] multi:是否执行多次
   * @return {Promise<[]>}
   */
  oracleTrans(sqlParams) {
    return new Promise(async (resolve, reject) => {
      let pool;
      try {
        pool = await this.createPool()
        let connection
        try {
          connection = await this.createConnection(pool)
          let results = []
          for (let i = 0, length = sqlParams.length; i < length; i++) {
            const {sql, params, multi = false, options = {}} = sqlParams[i]
            if (multi) results.push(await connection.executeMany(sql, params, options))
            else results.push(await connection.execute(sql, params, options))
          }
          // 提交事务
          await connection.commit()
          resolve(results)
        }catch (e) {
          // 事务回滚
          if (connection) {
            try {
              await connection.rollback()
              throw e
            } catch (e) {
              throw e
            }
          }
        } finally {
          if (connection) {
            try {
              await connection.close()
            } catch (e) {
              throw e
            }
          }
        }
      }catch (e) {
        reject(e)
      } finally {
        await pool.close()
      }
    })
  }
  
  /**
   * sql执行多次
   * @param sql
   * @param binds []
   * @param options
   */
  multiSql (sql, binds = [], options) {
    return new Promise(async (resolve, reject) => {
      let pool
      try {
        pool = await this.createPool()
        let connection
        try {
          connection = await this.createConnection(pool)
          const data = await connection.executeMany(sql, binds, options).catch(async e => {
            if (connection) {
              await connection.rollback()
              throw e
            }
          })
          // 提交事务
          await connection.commit()
          resolve(data)
        } catch (e) {
          throw e
        } finally {
          if (connection) {
            try {
              await connection.close()
            } catch (e) {
              throw e
            }
          }
        }
      } catch (e) {
        throw e
      } finally {
        await pool.close()
      }
    })
  }
}

const oracle = new Oracle();
module.exports = {
  async query(sql, mapping, params, options) {
    return await oracle.query(sql, mapping, params, options);
  },
  async insert (sql, params, options) {
    return await oracle.insert(sql, params, options);
  },
  async update (sql, params, options) {
    return await oracle.update(sql, params, options);
  },
  async delete (sql, params, options) {
    return await oracle.delete(sql, params, options);
  },
  async oracleTrans (sqlParams) {
    return await oracle.oracleTrans(sqlParams)
  },
  async multiSql (sql, binds, options) {
    return await oracle.multiSql(sql, binds, options)
  },
  async pageSql(sql, page, pageNum, mapping, params, options) {
    const newParams = {...params,
      maxRow:page * pageNum,
      minRow:(page - 1) * pageNum + 1}
    return await oracle.query(
      `SELECT * FROM (SELECT a.*, ROWNUM ROW_ID
        FROM (${sql}) a
        WHERE ROWNUM <= :maxRow)
        WHERE ROW_ID >= :minRow`,
      mapping,
      newParams,
      options
    )
  }
}

  上方工具包含了常用的CRUD操作及事务、分页、一个sql执行多次等操作。上方中出现的mapping为js中的变量与数据库中字段的映射,其数据类型如下:

const oracledb = require('oracledb')
// 角色信息映射
const ROLE_MAPPING = {
  roleId: {
    type: oracledb.NUMBER,
    name: 'ROLE_ID'
  },
  roleName: {
    type: oracledb.STRING,
    name: 'ROLE_NAME'
  },
  roleDesc: {
    type: oracledb.STRING,
    name: 'ROLE_DESC'
  }
}

module.exports = ROLE_MAPPING

使用方法:

const db = require('../database/index')
...
const data = await db.pageSql(`select ROlE_ID,ROLE_NAME, ROLE_DESC from SYS_ROLE ${searchSql} order by ROLE_ID`,
      pageNo, pageSize, ROLE_MAPPING, sqlParams)
      .catch(e => {throw e})
console.log(data)
// 返回的data结构
[
      {
        "roleId": 10001,
        "roleName": "管理员",
        "roleDesc": null,
        "rowId": 1
      },
      {
        "roleId": 10002,
        "roleName": "普通用户",
        "roleDesc": null,
        "rowId": 2
      },
      {
        "roleId": 10003,
        "roleName": "更新角色名",
        "roleDesc": "更新角色描述信息",
        "rowId": 3
      }
    ]
  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 可以使用 Node.jsoracledb 模块来连接 Oracle 数据库。 首先,需要安装 oracledb 模块: ``` npm install oracledb ``` 然后,使用 oracledb.getConnection() 方法来获取数据库连接,并在 options 参数中设置连接超时时间: ``` const oracledb = require('oracledb'); oracledb.getConnection( { user: 'username', password: 'password', connectString: 'host:port/service_name', options: { connectTimeout: 5000, // 设置连接超时时间为 5 秒 ... } }, function(err, connection) { // 连接成功后执行的回调函数 } ); ``` 连接超时时间的单位是毫秒,默认值为 60 秒。 注意:连接超时时间只是指连接 Oracle 数据库的超时时间,并不是数据库操作的超时时间。如果要设置数据库操作的超时时间,可以使用 oracledb.outFormat 和 oracledb.fetchAsBuffer 属性来实现。 ### 回答2: 在 Node.js 中设置连接 Oracle 数据库的超时时间可以通过以下步骤实现: 1. 首先,需要安装或引入适用于 Node.jsOracle 数据库驱动程序模块。常见的模块有 "oracledb"、"node-oracledb" 等。你可以通过 npm 包管理器来安装这些模块,例如,在终端中运行以下命令: ``` npm install oracledb ``` 2. 在代码中引入模块: ```javascript const oracledb = require('oracledb'); ``` 3. 创建 Oracle 数据库连接时,可以通过在连接选项中设置 `timeout` 属性来定义连接超时时间(以毫秒为单位)。例如: ```javascript const connectionOptions = { user: 'your_username', password: 'your_password', connectString: 'your_connection_string', timeout: 10000 // 设置连接超时时间为10秒 }; // 创建数据库连接 oracledb.getConnection(connectionOptions, function(err, connection) { if (err) { console.error(err.message); return; } // 连接成功,可以执行其他数据库操作 }); ``` 在上述代码中,`timeout` 属性被设置为 10000,即 10 秒。如果在 10 秒内无法成功建立数据库连接,则会触发超时错误。 通过上述步骤,你可以在 Node.js 中设置连接 Oracle 数据库的超时时间。根据你的需求,你可以根据实际情况调整超时时间。 ### 回答3: 在Node.js中,要设置连接Oracle数据库的超时时间,可以使用以下步骤进行操作: 1. 使用Node.js的包管理器(如npm)安装适用于Oracle数据库的适配器或驱动程序。一些常用的适配器包括oracledboracle-dbnode-oraclenode-oci8等。可以从npm的官方网站或在终端中使用命令`npm install`来安装。 2. 在Node.js的代码文件中引入适配器包并创建一个数据库连接对象。例如,使用oracledb适配器,可以使用以下代码进行连接: ```javascript const oracledb = require('oracledb'); // 设置连接Oracle数据库超时时间 oracledb.getConnection({ user: 'your_username', password: 'your_password', connectString: 'your_connect_string', timeout: 5000 // 设置超时时间为5秒 }, (err, connection) => { if (err) { console.error(err); return; } // 成功连接Oracle数据库 console.log('Connected to Oracle Database'); // 在这里可以执行其他数据库操作 }); ``` 在上述代码中,通过将timeout属性设置为5000,即设置超时时间为5秒。可以根据实际需求调整超时时间。 3. 在连接初始化时设置超时后,可以使用连接对象执行其他数据库操作,如查询数据、插入数据等。当数据库操作超过设置的超时时间后,连接将自动关闭,可以在回调函数中进行适当的错误处理。 总结:通过在创建数据库连接时设置timeout属性,可以在Node.js中设置连接Oracle数据库的超时时间。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MAXLZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值