NestJs:从多个数据库查询多个实体
NestJs: Query multiple entities from multiple database
我有mysql_server_1.database1.users
和mysql_server_2.database3.users_revenue
- 如何查询用户的行
- 如何从 users_revenue
中查询行
首先,我已经设置了连接:
const mysql1__database1 = TypeOrmModule.forRootAsync({
imports: [ConfigModule],
// @ts-ignore
useFactory: (configService: ConfigService) => ({
type: configService.get("DASHBOARD_DB_TYPE"),
host: configService.get("DASHBOARD_DB_HOST"),
port: configService.get("DASHBOARD_DB_PORT"),
username: configService.get("DASHBOARD_DB_USER"),
password: configService.get("DASHBOARD_DB_PASSWORD"),
database: configService.get("DASHBOARD_DB_NAME"),
entities: [__dirname + '/**/*.entity{.ts,.js}'],
// entities: [User],
autoLoadEntities: true,
synchronize: true,
}),
inject: [ConfigService],
});
const mysql2__database3 = TypeOrmModule.forRootAsync({
imports: [ConfigModule],
// @ts-ignore
useFactory: (configService: ConfigService) => ({
name: 'mysql2__database3',
type: configService.get("DASHBOARD2_DB_TYPE"),
host: configService.get("DASHBOARD2_DB_HOST"),
port: configService.get("DASHBOARD2_DB_PORT"),
username: configService.get("DASHBOARD2_DB_USER"),
password: configService.get("DASHBOARD2_DB_PASSWORD"),
database: configService.get("DASHBOARD2_DB_NAME"),
entities: [__dirname + '/**/*.entity{.ts,.js}'],
// entities: [User],
autoLoadEntities: true,
synchronize: true,
}),
inject: [ConfigService],
});
@Module({
imports: [
mysql1__database1,
mysql2__database3,
StatsModule,
],
controllers: [AppController],
providers: [AppService, StatsService],
})
export class AppModule {}
user.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';
@Injectable()
export class UserService {
constructor(@InjectRepository(User) private usersRepository: Repository<User>) {}
async findAll(): Promise<User[]> {
return await this.usersRepository.find();
}
}
然后这段代码 return 我的数据库中存在一个空数组而不是这么多行;
const items = await this.userService.findAll();
---更新---
我查看了 typeorm 源代码:
https://github.com/nestjs/typeorm/blob/8af34889fa7bf14d7dc5541beef1d5c2b50c2609/lib/common/typeorm.decorators.ts#L13
然后https://docs.nestjs.com/techniques/database#multiple-databases
At this point, you have User and Album entities registered with their own connection. With this setup, you have to tell the TypeOrmModule.forFeature() method and the @InjectRepository() decorator which connection should be used. If you do not pass any connection name, the default connection is used.
所以我认为它应该有效?
@InjectRepository(User, 'mysql2_database3')
@Module({
imports: [
TypeOrmModule.forFeature([User], "mysql2_database3"),
],
providers: [UserService],
controllers: [StatsController],
})
export class StatsModule {}
仍然出现错误:
Please make sure that the argument mysql2_database3Connection at index [0] is available in the TypeOrmModule context.
感谢 @jmc29
在 discord 上,他的指导很有帮助
解决方法是:
const mysql2__database3 = TypeOrmModule.forRootAsync({
imports: [ConfigModule],
// @ts-ignore
useFactory: (configService: ConfigService) => ({
name: 'mysql2__database3',
type: configService.get("DASHBOARD2_DB_TYPE"),
host: configService.get("DASHBOARD2_DB_HOST"),
port: configService.get("DASHBOARD2_DB_PORT"),
username: configService.get("DASHBOARD2_DB_USER"),
password: configService.get("DASHBOARD2_DB_PASSWORD"),
database: configService.get("DASHBOARD2_DB_NAME"),
entities: [__dirname + '/**/*.entity{.ts,.js}'],
autoLoadEntities: true,
synchronize: true,
}),
inject: [ConfigService],
});
再添加一行:
const mysql2__database3 = TypeOrmModule.forRootAsync({
name: 'mysql2__database3', // -----> Add this line, it's is required
imports: [ConfigModule],
// @ts-ignore
useFactory: (configService: ConfigService) => ({
name: 'mysql2__database3',
type: configService.get("DASHBOARD2_DB_TYPE"),
host: configService.get("DASHBOARD2_DB_HOST"),
port: configService.get("DASHBOARD2_DB_PORT"),
username: configService.get("DASHBOARD2_DB_USER"),
password: configService.get("DASHBOARD2_DB_PASSWORD"),
database: configService.get("DASHBOARD2_DB_NAME"),
entities: [__dirname + '/**/*.entity{.ts,.js}'],
autoLoadEntities: true,
synchronize: true,
}),
inject: [ConfigService],
});
对于遇到这个问题的人,这是我的解决方案
AppModule
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
load: [
database,
databaseAllo
]
}),
TypeOrmModule.forRootAsync({
useFactory: (configs: ConfigService) => configs.get("db_config"),
inject: [ConfigService],
}),
TypeOrmModule.forRootAsync({
name:"db_allo", <= create connection to my second db
useFactory: (configs: ConfigService) => configs.get("db_config_allo"),
inject: [ConfigService],
}),
AuthModule,
JwtAuthModule
],
controllers: []
})
export class AppModule {}
我的项目模块(包含来自第二个数据库的 table)
@Module({
imports: [
TypeOrmModule.forFeature([AlloMpcTable], "db_allo" <= call connection again),
],
providers: [
AlloRepository
],
exports: [AlloRepository],
controllers: [],
})
export class AlloModule {}
我的项目库
@Injectable()
export class AlloRepository extends BaseRepository<AlloMpcTable> {
constructor(
@InjectRepository(AlloMpcTable, "db_allo") <= you need to call connection again
private readonly allo: Repository<AlloMpcTable>,
) {
super(allo)
}
public async Find(id: number): Promise<AlloMpcTable> {
return await this.allo.findOne(id)
}
}
所以在你的情况下,你需要在你的提供者中再次调用“mysql2_database3”:[UserService]
我有mysql_server_1.database1.users
和mysql_server_2.database3.users_revenue
- 如何查询用户的行
- 如何从 users_revenue 中查询行
首先,我已经设置了连接:
const mysql1__database1 = TypeOrmModule.forRootAsync({
imports: [ConfigModule],
// @ts-ignore
useFactory: (configService: ConfigService) => ({
type: configService.get("DASHBOARD_DB_TYPE"),
host: configService.get("DASHBOARD_DB_HOST"),
port: configService.get("DASHBOARD_DB_PORT"),
username: configService.get("DASHBOARD_DB_USER"),
password: configService.get("DASHBOARD_DB_PASSWORD"),
database: configService.get("DASHBOARD_DB_NAME"),
entities: [__dirname + '/**/*.entity{.ts,.js}'],
// entities: [User],
autoLoadEntities: true,
synchronize: true,
}),
inject: [ConfigService],
});
const mysql2__database3 = TypeOrmModule.forRootAsync({
imports: [ConfigModule],
// @ts-ignore
useFactory: (configService: ConfigService) => ({
name: 'mysql2__database3',
type: configService.get("DASHBOARD2_DB_TYPE"),
host: configService.get("DASHBOARD2_DB_HOST"),
port: configService.get("DASHBOARD2_DB_PORT"),
username: configService.get("DASHBOARD2_DB_USER"),
password: configService.get("DASHBOARD2_DB_PASSWORD"),
database: configService.get("DASHBOARD2_DB_NAME"),
entities: [__dirname + '/**/*.entity{.ts,.js}'],
// entities: [User],
autoLoadEntities: true,
synchronize: true,
}),
inject: [ConfigService],
});
@Module({
imports: [
mysql1__database1,
mysql2__database3,
StatsModule,
],
controllers: [AppController],
providers: [AppService, StatsService],
})
export class AppModule {}
user.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';
@Injectable()
export class UserService {
constructor(@InjectRepository(User) private usersRepository: Repository<User>) {}
async findAll(): Promise<User[]> {
return await this.usersRepository.find();
}
}
然后这段代码 return 我的数据库中存在一个空数组而不是这么多行;
const items = await this.userService.findAll();
---更新--- 我查看了 typeorm 源代码: https://github.com/nestjs/typeorm/blob/8af34889fa7bf14d7dc5541beef1d5c2b50c2609/lib/common/typeorm.decorators.ts#L13
然后https://docs.nestjs.com/techniques/database#multiple-databases
At this point, you have User and Album entities registered with their own connection. With this setup, you have to tell the TypeOrmModule.forFeature() method and the @InjectRepository() decorator which connection should be used. If you do not pass any connection name, the default connection is used.
所以我认为它应该有效?
@InjectRepository(User, 'mysql2_database3')
@Module({
imports: [
TypeOrmModule.forFeature([User], "mysql2_database3"),
],
providers: [UserService],
controllers: [StatsController],
})
export class StatsModule {}
仍然出现错误:
Please make sure that the argument mysql2_database3Connection at index [0] is available in the TypeOrmModule context.
感谢 @jmc29
在 discord 上,他的指导很有帮助
解决方法是:
const mysql2__database3 = TypeOrmModule.forRootAsync({
imports: [ConfigModule],
// @ts-ignore
useFactory: (configService: ConfigService) => ({
name: 'mysql2__database3',
type: configService.get("DASHBOARD2_DB_TYPE"),
host: configService.get("DASHBOARD2_DB_HOST"),
port: configService.get("DASHBOARD2_DB_PORT"),
username: configService.get("DASHBOARD2_DB_USER"),
password: configService.get("DASHBOARD2_DB_PASSWORD"),
database: configService.get("DASHBOARD2_DB_NAME"),
entities: [__dirname + '/**/*.entity{.ts,.js}'],
autoLoadEntities: true,
synchronize: true,
}),
inject: [ConfigService],
});
再添加一行:
const mysql2__database3 = TypeOrmModule.forRootAsync({
name: 'mysql2__database3', // -----> Add this line, it's is required
imports: [ConfigModule],
// @ts-ignore
useFactory: (configService: ConfigService) => ({
name: 'mysql2__database3',
type: configService.get("DASHBOARD2_DB_TYPE"),
host: configService.get("DASHBOARD2_DB_HOST"),
port: configService.get("DASHBOARD2_DB_PORT"),
username: configService.get("DASHBOARD2_DB_USER"),
password: configService.get("DASHBOARD2_DB_PASSWORD"),
database: configService.get("DASHBOARD2_DB_NAME"),
entities: [__dirname + '/**/*.entity{.ts,.js}'],
autoLoadEntities: true,
synchronize: true,
}),
inject: [ConfigService],
});
对于遇到这个问题的人,这是我的解决方案
AppModule
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
load: [
database,
databaseAllo
]
}),
TypeOrmModule.forRootAsync({
useFactory: (configs: ConfigService) => configs.get("db_config"),
inject: [ConfigService],
}),
TypeOrmModule.forRootAsync({
name:"db_allo", <= create connection to my second db
useFactory: (configs: ConfigService) => configs.get("db_config_allo"),
inject: [ConfigService],
}),
AuthModule,
JwtAuthModule
],
controllers: []
})
export class AppModule {}
我的项目模块(包含来自第二个数据库的 table)
@Module({
imports: [
TypeOrmModule.forFeature([AlloMpcTable], "db_allo" <= call connection again),
],
providers: [
AlloRepository
],
exports: [AlloRepository],
controllers: [],
})
export class AlloModule {}
我的项目库
@Injectable()
export class AlloRepository extends BaseRepository<AlloMpcTable> {
constructor(
@InjectRepository(AlloMpcTable, "db_allo") <= you need to call connection again
private readonly allo: Repository<AlloMpcTable>,
) {
super(allo)
}
public async Find(id: number): Promise<AlloMpcTable> {
return await this.allo.findOne(id)
}
}
所以在你的情况下,你需要在你的提供者中再次调用“mysql2_database3”:[UserService]