如何在Node.js中使用TypeORM连接Oracle数据库及将db.js迁移为TS
TypeORM连接Oracle云自治数据库解决方案
你当前TypeORM连接失败的核心原因有两个:
- 未在初始化连接前调用
oracledb.initOracleClient()加载本地Oracle Instant Client - 连接配置缺失必要的自治库连接参数,Oracle云自治数据库需要匹配TNS别名或完整连接串配置
修正后的TypeORM代码(兼容0.2.x版本)
import { createConnection } from "typeorm"; import oracledb from "oracledb"; // 可直接复用你原有可用的dbconfig配置 import dbConfig from "./dbconfig"; // 必须先初始化Oracle客户端,再创建连接 oracledb.initOracleClient({ libDir: process.env.ORACLE_CLIENT_PATH || "D:\\MaterialSkywork\\Oracle\\instantclient_21_3" }); createConnection({ type: "oracle", username: dbConfig.user, password: dbConfig.password, // 自治数据库的TNS别名,对应你钱包中tnsnames.ora里的DBxxx_high配置 connectString: dbConfig.connectString, synchronize: process.env.NODE_ENV === "development", // 生产环境务必关闭 logging: process.env.NODE_ENV === "development", // 额外oracledb配置可放在extra中 extra: { autoCommit: false } }).then(connection => { console.log('数据库连接成功') }).catch(error => console.log('连接失败:', error));
如果你使用的是TypeORM 0.3.x及以上版本,createConnection已废弃,请改用DataSource初始化:
import { DataSource } from "typeorm"; import oracledb from "oracledb"; import dbConfig from "./dbconfig"; oracledb.initOracleClient({ libDir: process.env.ORACLE_CLIENT_PATH || "D:\\MaterialSkywork\\Oracle\\instantclient_21_3" }); export const AppDataSource = new DataSource({ type: "oracle", username: dbConfig.user, password: dbConfig.password, connectString: dbConfig.connectString, synchronize: process.env.NODE_ENV === "development", logging: process.env.NODE_ENV === "development", entities: [/* 你的实体类路径 */] }) // 初始化连接 AppDataSource.initialize() .then(() => console.log('数据库连接成功')) .catch(err => console.error('连接失败:', err))
原生db.js迁移TypeScript方案
如果暂时不使用TypeORM,可按以下方案将原有可用的js代码转为TS:
- 首先安装类型依赖:
npm install @types/oracledb --save-dev - 编写
db.ts文件:
import oracledb, { BindParameters, Result } from "oracledb"; import dbConfig from "./dbconfig"; import dotenv from "dotenv"; dotenv.config(); // 初始化Oracle客户端 oracledb.initOracleClient({ libDir: process.env.ORACLE_CLIENT_PATH || "D:\\MaterialSkywork\\Oracle\\instantclient_21_3" }); // 初始化连接池(比每次新建连接性能更高) async function initPool() { await oracledb.createPool({ ...dbConfig, poolMin: 2, poolMax: 10, poolIncrement: 1 }); } initPool().catch(err => console.error('连接池初始化失败:', err)); /** * 执行SQL查询 * @param sql SQL语句 * @param binds 绑定参数,避免SQL注入 * @param autoCommit 是否自动提交 */ export async function Open<T = any>(sql: string, binds: BindParameters = [], autoCommit: boolean = false): Promise<Result<T>> { let connection; try { // 从连接池获取连接 connection = await oracledb.getConnection(); // 配置返回格式为对象,无需手动按下标映射字段 return await connection.execute<T>(sql, binds, { autoCommit, outFormat: oracledb.OUT_FORMAT_OBJECT }); } finally { if (connection) { // 确保连接释放回连接池 await connection.close(); } } }
迁移后你的业务查询代码可以简化为:
import { Open } from './db'; async function start() { const sql = "select * from elopez.orders"; const result = await Open(sql, [], false); // 直接返回对象数组,无需手动映射 const orders = result.rows; console.log(orders); } start();
最佳实践建议
- 安全类
- 绝对不要在生产环境开启
synchronize: true,该配置会自动根据实体类修改数据库表结构,存在数据丢失风险 - 敏感信息(密码、客户端路径、TNS配置路径)不要硬编码在代码中,使用
dotenv加载.env文件配置,.env文件不要提交到代码仓库 - 所有SQL查询必须使用参数绑定(即你原有代码中的binds参数),禁止拼接SQL字符串,避免SQL注入漏洞
- 业务代码不要使用admin账号连接数据库,按需创建权限最小化的业务账号
- 绝对不要在生产环境开启
- 性能稳定性类
- 推荐使用连接池管理数据库连接,避免每次请求新建/销毁连接的性能开销,同时控制连接数上限避免数据库压力过大
- 所有数据库操作必须添加异常捕获,使用
try/finally确保连接正常释放,避免连接泄漏
- 工程化类
- Oracle客户端路径根据不同环境(Windows/Mac/Linux)通过环境变量配置,不要硬编码固定路径
- 查询时开启
outFormat: oracledb.OUT_FORMAT_OBJECT直接返回键值对对象,避免按下标取值出现字段匹配错误
内容的提问来源于stack exchange,提问作者Edisson Gabriel López
相关产品推荐
相关产品推荐

