【问题标题】:Why TypeORM requires the second parameter, inverseSide property (even though it's optional)为什么 TypeORM 需要第二个参数 inverseSide 属性(即使它是可选的)
【发布时间】:2021-01-24 13:08:18
【问题描述】:

我正在同时使用 NestJS 学习 Typescript 和 TypeORM。最近,我遇到了一个使用 OneToMany 和 ManyToOne 关系装饰器的用例。提前,我注意到将 OneToMany 和 ManyToOne 关系放在一起,开发人员经常将 OneToMany 属性作为 ManyToOne 的第二个参数,例如

@ManyToOne(type => User, user => user.photos)

我想知道为什么那里需要user.photos,我试过没有user.photos,它似乎工作正常,我很担心这个属性,谁能帮我澄清一下这个问题?非常感谢。

为了提供更多背景信息,这里有一个我不太清楚的推荐链接。感谢您的所有指导:- Why does TypeORM require the inverse side of OneToMany to be provided, but doesn't require the inverse side of ManyToOne to be provided?

【问题讨论】:

    标签: typescript nestjs typeorm


    【解决方案1】:

    tldr

    它在元模型构建、验证、一些错误消息和QueryBuilder API 期间使用。

    没有它,TypeORM 似乎可以正常工作的原因是您可能错过了它会失败的特定用例。


    如果您检查其中一个映射装饰器的来源,例如 OneToOne,您将看到该值是如何使用的:

    https://github.com/typeorm/typeorm/blob/master/src/decorator/relations/OneToOne.ts#L53

    export function OneToOne<T>(typeFunctionOrTarget: string|((type?: any) => ObjectType<T>),
                            inverseSideOrOptions?: string|((object: T) => any)|RelationOptions,
                            options?: RelationOptions): PropertyDecorator {
    
    // ...
    
    return function (object: Object, propertyName: string) {
        // ...
    
        getMetadataArgsStorage().relations.push({
            // ...
            inverseSideProperty: inverseSideProperty,
            // ...
        } as RelationMetadataArgs);
    

    搜索 repo 并跟踪您将看到的属性的用法,它最终用于在元模型对象上生成 inverseRelation 属性,该属性稍后用于进一步的元模型构建、错误报告、元模型验证和QueryBuilder

    https://github.com/typeorm/typeorm/blob/f27622daf9784d06496975bbbcacdb0938fd2c82/src/metadata/RelationMetadata.ts#L281

    export class RelationMetadata {
    
    // ...
    
    constructor(options: {
        entityMetadata: EntityMetadata,
        embeddedMetadata?: EmbeddedMetadata,
        args: RelationMetadataArgs
    }) {
        
        // ...
    
        if (args.inverseSideProperty)
            this.givenInverseSidePropertyFactory = args.inverseSideProperty;
    
        // ...
    

    https://github.com/typeorm/typeorm/blob/f27622daf9784d06496975bbbcacdb0938fd2c82/src/metadata/RelationMetadata.ts#L521

    buildInverseSidePropertyPath(): string {
    
        if (this.givenInverseSidePropertyFactory) {
            const ownerEntityPropertiesMap = this.inverseEntityMetadata.propertiesMap;
            if (typeof this.givenInverseSidePropertyFactory === "function")
                return this.givenInverseSidePropertyFactory(ownerEntityPropertiesMap);
    
            if (typeof this.givenInverseSidePropertyFactory === "string")
                return this.givenInverseSidePropertyFactory;
    
        }
    
        // ...
    
        return "";
    }
    

    https://github.com/typeorm/typeorm/blob/f27622daf9784d06496975bbbcacdb0938fd2c82/src/metadata-builder/EntityMetadataBuilder.ts#L667

    protected computeInverseProperties(entityMetadata: EntityMetadata, entityMetadatas: EntityMetadata[]) {
        entityMetadata.relations.forEach(relation => {
    
            // ...
    
            relation.inverseEntityMetadata = inverseEntityMetadata;
            relation.inverseSidePropertyPath = relation.buildInverseSidePropertyPath();
    
            // and compute inverse relation and mark if it has such
            relation.inverseRelation = inverseEntityMetadata.relations.find(foundRelation => foundRelation.propertyPath === relation.inverseSidePropertyPath);
        });
    

    此时,您可以搜索.inverseRelation的用途,您将有一个很好的起点来回答您的问题。

    请注意,有几个使用上述属性的禁用验证(在 cmets 内):https://github.com/typeorm/typeorm/blob/f27622daf9784d06496975bbbcacdb0938fd2c82/src/metadata-builder/EntityMetadataValidator.ts#L133-L187


    【讨论】:

      猜你喜欢
      • 2021-12-20
      • 2011-11-19
      • 2013-07-08
      • 1970-01-01
      • 1970-01-01
      • 2017-12-28
      • 1970-01-01
      • 2016-07-27
      • 2018-04-19
      相关资源
      最近更新 更多