实体之间的循环依赖

问题描述 投票:0回答:5

我有三个实体 TestUser 、 TestProfile 和 TestPhoto,其中 TestUser 与 TestProfile 具有一对一关系,TestProfiles 与 TestPhoto 具有一对一关系,最后 TestPhoto 与 User 具有多对一关系,该关系可能尚未创建

我在定义我的实体时使用级联,我希望在我的 UserService 中通过一次调用来创建它们,但面临这个循环依赖:“TestPhoto”错误并且从那时起没有任何进展,我认为它可能不应该做什么在现实生活中,但除此之外,还有任何可能的黑客攻击或者根本不可能吗?

@Entity()
@Unique(["name"])
export class TestUser {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    name: string;

    @OneToOne(() => TestProfile,{
        cascade:true,
        nullable:true
    })
    @JoinColumn()
    profile: TestProfile;
    @Column({nullable:true})
    profileId: number

    @OneToMany(() => TestPhoto, photo => photo.user)
    photos: TestPhoto[];

}


@Entity()
export class TestProfile {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    gender: string;

    @OneToOne(type=>TestPhoto,{
        cascade:true,
        nullable:true
    })
    @JoinColumn()
    photo: TestPhoto;

    @Column({nullable:true})
    photoId: number

}

@Entity()
export class TestPhoto {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    url: string;

    @ManyToOne(() => TestUser, user => user.photos,{
        cascade:true,
        nullable:true
    })
    user: TestUser;
    @Column({nullable:true})
    userId: number; 

}

在我的 UserService 中抽象了如下调用

const user = new TestUser(); 
const profile1 = new TestProfile(); 
const photo1 = new TestPhoto(); 
photo1.user = user;
profile1.photo  = photo1; 
user.profile = profile1

await connection.manager.save(user);  
node.js postgresql nestjs typeorm
5个回答
2
投票

这些实体是否位于同一个文件中?

我使用

import type
TS 的功能来解决模块解析级别的循环依赖。我不确定这是否是你的情况。


1
投票

我用 typeorm 解决了这个问题 Relation 在这里解释 tyopeorm 实体循环依赖


0
投票

在编写代码之前,请先了解循环依赖的概念; 链接。在您的情况下可能存在循环依赖,但在现实生活场景中可能不会。你所要做的就是让你的实体/模态在双方都成为forwardRef。然后使用另一个服务的构造函数内的

@Inject(forwardRef(() => YourService))
使服务能够注入到其他服务中。如果您不明白,我将发布一个完整的示例,说明循环依赖在您的案例和现实生活场景中如何工作。


0
投票

当存在循环依赖问题时,我使用通用导入文件

// common.ts
// also it's important to keep order, parent first and then...
export * from './parent.entity';
export * from './child1.entity';
export * from './child2.entity';

// parent.entity.ts ------------------------------------
import { Child1Entity, Child2Entity } from './common.ts'

export class ParentEntity {
    @OneToOne(() => Child1Entity, child => child.parent)
    public child1: Child1Entity[];

    @OneToOne(() => Child2Entity, child => child.parent)
    public child2: Child2Entity[];
}

// child1.entity.ts ----------------------
import { ParentEntity } from './common.ts'

export class Child1Entity extends Parent {
    @OneToOne(() => ParentEntity, parent => parent.child1)
    @JoinColumn()
    public parent: ParentEntity;
}

// child2.entity.ts ----------------------
import { ParentEntity } from './common.ts'

export class Child2Entity extends Parent {
    @OneToOne(() => ParentEntity, parent => parent.child2)
    @JoinColumn()
    public parent: ParentEntity;
}

这个模式可以帮助你解决各种循环依赖问题


0
投票

在 Typeorm 中,关系装饰器(@OneToMany、@ManyToOne、@OneToOne 和 ManyToMany)接受以下参数:

export declare function OneToMany<T>(typeFunctionOrTarget: string | ((type?: any) => ObjectType<T>), inverseSide: string | ((object: T) => any), options?: RelationOptions): PropertyDecorator;

如您所见,您可以提供 typeFunctionOrTarget (第一个参数)类型作为字符串,它可以防止 Typeorm 循环依赖错误。 就我而言,以下方法解决了循环依赖问题:

@OneToMany(
    'CollectionPhase',
    (collectionPhase: CollectionPhase) => collectionPhase.collectionNo,
  )
  phases?: Relation<CollectionPhase[]>;
© www.soinside.com 2019 - 2024. All rights reserved.