Nest.js多数据库配置异常:Atendente实体元数据未找到
项目信息
- Nest.js
- @nestjs/typeorm v9.0.1
- oracledb 5.5.0
- typeorm v0.3.15
- Windows 10
- Node v16.18.0
- Npm v9.4.2
错误日志
[Nest] 24652 - 16/05/2023 13:07:45 ERROR [ExceptionsHandler] No metadata for "Atendente" was found. EntityMetadataNotFoundError: No metadata for "Atendente" was found.
{ "statusCode": 500, "message": "Internal server error" }
其他日志
sei database using logging = true: query: SELECT SYS_CONTEXT('USERENV','DB_NAME') AS "db_name" FROM dual query: SELECT SYS_CONTEXT('USERENV','DB_NAME') AS "db_name" FROM dual pad database using logging = true: query: SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') AS "schema_name" FROM dual query: SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') AS "schema_name" FROM dual
项目结构
配置了两个Oracle数据库:
- 默认数据库sei(无name配置):
// src/database/sei.database.ts import { TypeOrmModuleOptions } from '@nestjs/typeorm'; import * as dotenv from 'dotenv'; dotenv.config(); export const seiDatabase: TypeOrmModuleOptions = { type: 'oracle', host: process.env.SEI_CONNECTION_STRING_PROD, port: 1521, username: process.env.SEI_ORACLE_USER_PROD, password: process.env.SEI_ORACLE_PWD_PROD, sid: process.env.SEI_CONNECTION_SID_PROD, entities: [__dirname + '/../sei/**/*.entity{.ts,.js}'], synchronize: false, logging: true, };
- 命名为pad的数据库:
// /src/database/pad.database.ts import { TypeOrmModuleOptions } from '@nestjs/typeorm'; import * as dotenv from 'dotenv'; dotenv.config(); export const padDatabase: TypeOrmModuleOptions = { name: 'pad', type: 'oracle', host: process.env.PAD_CONNECTION_STRING_PROD, port: 1521, username: process.env.PAD_ORACLE_USER_PROD, password: process.env.PAD_ORACLE_PWD_PROD, sid: process.env.PAD_CONNECTION_SID_PROD, entities: [__dirname + '/../pad/**/*.entity{.ts,.js}'], synchronize: false, logging: true, };
模块配置
- app.module.ts:
// /src/app.module.ts import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { DatabaseModule } from './database/database.module'; import { UsuariosModule } from './sei/usuarios/usuarios.module'; @Module({ imports: [ DatabaseModule, AtendentesModule, UsuariosModule, ], controllers: [AppController], providers: [AppService], }) export class AppModule {}
- Atendentes模块(对应pad数据库):
// /src/pad/atendentes.module.ts: import { TypeOrmModule } from '@nestjs/typeorm'; import { Module } from '@nestjs/common'; import { AtendentesController } from './atendentes.controller'; import { AtendentesService } from './atendentes.service'; import { Atendente } from './entities/atendente.entity'; @Module({ imports: [TypeOrmModule.forFeature([Atendente])], controllers: [AtendentesController], providers: [AtendentesService], }) export class AtendentesModule {}
- Usuarios模块(对应sei数据库):
// src/sei/usuarios.module.ts import { TypeOrmModule } from '@nestjs/typeorm'; import { Module } from '@nestjs/common'; import { UsuariosController } from './usuarios.controller'; import { UsuariosService } from './usuarios.service'; import { Usuario } from './entities/usuario.entity'; @Module({ imports: [TypeOrmModule.forFeature([Usuario])], controllers: [UsuariosController], providers: [UsuariosService], }) export class UsuariosModule {}
问题描述
Usuarios模块可正常工作,说明默认sei数据源连接正常,但Atendentes模块无法找到Atendente实体的元数据,无法正常连接pad数据库。目前发现只有未配置name的数据库能建立连接,若移除pad数据库的name配置则可连接,但需要给sei数据库添加name才能避免冲突,求解决该多数据库配置问题。
解决方案
问题核心是多数据库场景下,TypeOrmModule.forFeature()未指定对应数据库连接名称,导致Nest默认用无name的连接查找pad数据库的实体,因此找不到元数据。
修复步骤:
- 给sei数据库添加name配置,避免连接混淆:
修改sei.database.ts,新增name: 'sei':
export const seiDatabase: TypeOrmModuleOptions = { name: 'sei', // 新增name配置 type: 'oracle', host: process.env.SEI_CONNECTION_STRING_PROD, port: 1521, username: process.env.SEI_ORACLE_USER_PROD, password: process.env.SEI_ORACLE_PWD_PROD, sid: process.env.SEI_CONNECTION_SID_PROD, entities: [__dirname + '/../sei/**/*.entity{.ts,.js}'], synchronize: false, logging: true, };
- 在各模块的
TypeOrmModule.forFeature()中指定对应数据库name:
- 修改Atendentes模块(对应pad数据库):
@Module({ imports: [TypeOrmModule.forFeature([Atendente], 'pad')], // 传入数据库name controllers: [AtendentesController], providers: [AtendentesService], }) export class AtendentesModule {}
- 修改Usuarios模块(对应sei数据库):
@Module({ imports: [TypeOrmModule.forFeature([Usuario], 'sei')], // 传入数据库name controllers: [UsuariosController], providers: [UsuariosService], }) export class UsuariosModule {}
- 确认DatabaseModule正确注册两个数据库连接:
确保database.module.ts中同时导入两个配置:
import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { seiDatabase } from './sei.database'; import { padDatabase } from './pad.database'; @Module({ imports: [ TypeOrmModule.forRoot(seiDatabase), TypeOrmModule.forRoot(padDatabase), ], }) export class DatabaseModule {}
额外注意
如果Service中使用@InjectRepository(),也需要指定对应数据库name:
constructor( @InjectRepository(Atendente, 'pad') // 传入数据库name private atendenteRepository: Repository<Atendente>, ) {}
配置完成后,Nest能正确识别每个实体对应的数据库连接,元数据找不到的问题即可解决。
内容的提问来源于stack exchange,提问作者Lucas Marra
相关产品推荐
相关产品推荐

