我正在使用Nest.js,并考虑从TypeORM迁移到Mikro-ORM。我正在使用nestjs-mikro-orm
模块。但是我被困在一个看起来很简单的东西上……
我有3个实体,AuthorEntity
,BookEntity
和BookMetadata
。在我的Author
模块中,我尝试使用Book
方法将BookMetadata
和createQueryBuilder
表联接在一起。但是运行查询时,在Collection<BookEntity> of entity AuthorEntity[3390] not initialized
处出现错误。不过,Author
表中的列可以很好地检索。
我的3个实体:
@Entity()
@Unique({ properties: ['key'] })
export class AuthorEntity {
@PrimaryKey()
id!: number;
@Property({ length: 255 })
key!: string;
@OneToMany('BookEntity', 'author', { orphanRemoval: true })
books? = new Collection<BookEntity>(this);
}
@Entity()
export class BookEntity {
@PrimaryKey()
id!: number;
@ManyToOne(() => AuthorEntity)
author!: AuthorEntity;
@OneToMany('BookMetadataEntity', 'book', { orphanRemoval: true })
bookMetadata? = new Collection<BookMetadataEntity>(this);
}
@Entity()
@Unique({ properties: ['book', 'localeKey'] })
export class BookMetadataEntity {
@PrimaryKey()
id!: number;
@Property({ length: 5 })
localeKey!: string;
@ManyToOne(() => BookEntity)
book!: BookEntity;
}
运行查询的服务文件:
@Injectable()
export class AuthorService {
constructor(
@InjectRepository(AuthorEntity)
private readonly authorRepository: EntityRepository<AuthorEntity>,
) {}
async findOneByKey(props: { key: string; localeKey: string; }): Promise<AuthorEntity> {
const { key, localeKey } = props;
return this.authorRepository
.createQueryBuilder('a')
.select(['a.*', 'b.*', 'c.*'])
.leftJoin('a.books', 'b')
.leftJoin('b.bookMetadata', 'c')
.where('a.key = ?', [key])
.andWhere('c.localeKey = ?', [localeKey])
.getSingleResult();
}
}
我错过了什么吗?可能没有关系,但我也注意到使用Nest.js的TypeORM用户有a special autoLoadEntities: true
。 Mikro-ORM有类似的东西吗?谢谢;)
答案 0 :(得分:1)
尚不支持从单个查询映射多个实体,这已计划用于v4。您可以在此处订阅:https://github.com/mikro-orm/mikro-orm/issues/440
在v3中,您需要使用2个查询来加载2个实体,这对于您的用例而言,没有QB的情况要容易得多。
return this.authorRepository.findOne({ key }, ['books']);
或者您可以使用qb.execute()
来获取原始结果并自己映射它们,但是您还必须手动别名所有字段来避免重复(Author.name
与Book.name
) ,因为进行qb.select(['a.*', 'b.*'])
会导致查询select a.*, b.* ...
,并且重复的列将无法正确映射。
https://mikro-orm.io/docs/query-builder/#mapping-raw-results-to-entities
关于autoLoadEntities
的事情,从来没有听说过,它将看一下它是如何工作的,但是总的来说,nestjs适配器不是我开发的,所以如果它只与嵌套有关,那会更好问他们的GH回购。
或者您可以使用基于文件夹的发现(entitiesDirs
)。
这是包含3个实体的新示例:
return this.authorRepository.findOne({
key,
books: { bookMetadata: localeKey } },
}, ['books.bookMetadata']);
这将产生3个查询,每个db表一个,但是第一个查询将自动联接book和bookMetadata以能够被它们过滤。该条件将在第二和第三查询中向下传播。
如果您省略填充参数(['books.bookMetadata']
),则仅会触发第一个查询,并且最终会导致书籍没有填充(但将向作者查询合并条件)。