在TypeORM中为私有实体属性定义多个关联关系。

huangapple go评论59阅读模式
英文:

Defining many relations in typeorm for private entity properties

问题

I'm using the typeorm library for entity mapping in my node app. I want to include many type relations between entities. I have followed the docs, and in it, the entity properties are marked as public so we can access them from other entities. However, I have defined entity properties as private. So, I have created a getProperty method in the entity to retrieve the property on the entity instance. Now, typeorm throws an error saying entity.getProperty is not a function.

User Entity

@Entity()
class User {

    private USER_ID_PREFIX: string = "uid-";

    @PrimaryColumn()
    private id: string;
    @Column({nullable: false, length: 15})
    private firstname: string;
    @Column({nullable: false, length: 15})
    private lastname: string;
    @Column({nullable: false, unique: true, length: 25})
    private email: string;
    @Column({nullable: false})
    private password: string;
    @OneToMany(() => Role, (role) => role.getProperty(EntityProperty.USER))
    private roles: Role[];

    public constructor(...args: any[]) {
        if (args.length === 0)
            return;
        if (args.length === 1) {
            if (args[0] instanceof UserCreateRequestDto) {
                let requestDto = args[0];
                this.id = this.USER_ID_PREFIX + randomUUID();
                this.firstname = requestDto.getProperty(DtoProperty.FIRSTNAME);
                this.lastname = requestDto.getProperty(DtoProperty.LASTNAME);
                this.email = requestDto.getProperty(DtoProperty.EMAIL);
                this.password = requestDto.getProperty(DtoProperty.PASSWORD);
            }
        }
    }

    public getProperty(property: EntityProperty): any {
        if (property === EntityProperty.ID)
            return this.id;
        if (property === EntityProperty.FIRSTNAME)
            return this.firstname;
        if (property === EntityProperty.LASTNAME)
            return this.lastname;
        if (property === EntityProperty.EMAIL)
            return this.email;
        if (property === EntityProperty.PASSWORD)
            return this.password;
        if (property === EntityProperty.ROLES)
            return this.roles;
        throw new Error(`No such entity property as ${property.toString()} exists in User`);
    }
}

export default User;

Role Entity

@Entity()
class Role {

    private ROLE_ID_PREFIX: string = "rid-";

    @PrimaryColumn()
    private id: string;
    @Column({nullable: false})
    private role: string;
    @ManyToOne(() => User, (user) => user.getProperty(EntityProperty.ROLES))
    private user: User;

    public constructor(...args: any[]) {
        if (args.length === 0)
            return;
        if (args.length === 1) {
            if (args[0] instanceof RoleCreateRequestDto) {
                let requestDto = args[0];
                this.id = this.ROLE_ID_PREFIX + randomUUID();
                this.role = requestDto.getProperty(DtoProperty.ROLE);
            }
        }
    }

    public getProperty(property: EntityProperty): any {
        if (property === EntityProperty.ID)
            return this.id;
        if (property === EntityProperty.ROLE)
            return this.role;
        if (property === EntityProperty.USER)
            return this.user;
        throw new Error(`No such entity property as ${property.toString()} exists in Role`);
    }
}

export default Role;

Error stack

query: SELECT VERSION() AS `version`
Error initializing MySQL datasource TypeError: user.getProperty is not a function
    at RelationMetadata.givenInverseSidePropertyFactory (D:\Swivel_Projects\Ignite\Project 1\backend\ignite-auth-nodejs\src\entities\Role.ts:22:43)
    at RelationMetadata.buildInverseSidePropertyPath (D:\Swivel_Projects\Ignite\Project 1\backend\ignite-auth-nodejs\node_modules\src\metadata\RelationMetadata.ts:628:29)
    at D:\Swivel_Projects\Ignite\Project 1\backend\ignite-auth-nodejs\node_modules\src\metadata-builder\EntityMetadataBuilder.ts:1116:26
    at Array.forEach (<anonymous>)
    at EntityMetadataBuilder.computeInverseProperties (D:\Swivel_Projects\Ignite\Project 1\backend\ignite-auth-nodejs\node_modules\src\metadata-builder\EntityMetadataBuilder.ts:1096:34)
    at D:\Swivel_Projects\Ignite\Project 1\backend\ignite-auth-nodejs\node_modules\src\metadata-builder\EntityMetadataBuilder.ts:158:18
    at Array.forEach (<anonymous>)
    at EntityMetadataBuilder.build (D:\Swivel_Projects\Ignite\Project 1\backend\ignite-auth-nodejs\node_modules\src\metadata-builder\EntityMetadataBuilder.ts:157:25)
    at ConnectionMetadataBuilder.buildEntityMetadatas (D:\Swivel_Projects\Ignite\Project 1\backend\ignite-auth-nodejs\node_modules\src\connection\ConnectionMetadataBuilder.ts:106:11)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
英文:

I'm using typeorm library for entity mapping in my node app. I want to include many type relations between entities. I have followed the docs and in it the entity properties are marked as public, so we can access it from other entities. I have defined entity properties as private. So I have created a getProperty method in entity to give back the property on entity instance. Now typeorm throws an error saying entity.getProperty is not a function.

User Entity

@Entity()
class User {
private USER_ID_PREFIX: string = &quot;uid-&quot;;
@PrimaryColumn()
private id: string;
@Column({nullable: false, length: 15})
private firstname: string;
@Column({nullable: false, length: 15})
private lastname: string;
@Column({nullable: false, unique: true, length: 25})
private email: string;
@Column({nullable: false})
private password: string;
@OneToMany(() =&gt; Role, (role) =&gt; role.getProperty(EntityProperty.USER))
private roles: Role[];
public constructor(...args: any[]) {
if (args.length === 0)
return;
if (args.length === 1) {
if (args[0] instanceof UserCreateRequestDto) {
let requestDto = args[0];
this.id = this.USER_ID_PREFIX + randomUUID();
this.firstname = requestDto.getProperty(DtoProperty.FIRSTNAME);
this.lastname = requestDto.getProperty(DtoProperty.LASTNAME);
this.email = requestDto.getProperty(DtoProperty.EMAIL);
this.password = requestDto.getProperty(DtoProperty.PASSWORD);
}
}
}
public getProperty(property: EntityProperty): any {
if (property === EntityProperty.ID)
return this.id;
if (property === EntityProperty.FIRSTNAME)
return this.firstname;
if (property === EntityProperty.LASTNAME)
return this.lastname;
if (property === EntityProperty.EMAIL)
return this.email;
if (property === EntityProperty.PASSWORD)
return this.password;
if (property === EntityProperty.ROLES)
return this.roles;
throw new Error(`No such entity property as ${property.toString()} exists in User`);
}
}
export default User;

Role Entity

@Entity()
class Role {
private ROLE_ID_PREFIX: string = &quot;rid-&quot;;
@PrimaryColumn()
private id: string;
@Column({nullable: false})
private role: string;
@ManyToOne(() =&gt; User, (user) =&gt; user.getProperty(EntityProperty.ROLES))
private user: User;
public constructor(...args: any[]) {
if (args.length === 0)
return;
if (args.length === 1) {
if (args[0] instanceof RoleCreateRequestDto) {
let requestDto = args[0];
this.id = this.ROLE_ID_PREFIX + randomUUID();
this.role = requestDto.getProperty(DtoProperty.ROLE);
}
}
}
public getProperty(property: EntityProperty): any {
if (property === EntityProperty.ID)
return this.id;
if (property === EntityProperty.ROLE)
return this.role;
if (property === EntityProperty.USER)
return this.user;
throw new Error(`No such entity property as ${property.toString()} exists in Role`);
}
}
export default Role;

Error stack

query: SELECT VERSION() AS `version`
Error initializing mysql datasource TypeError: user.getProperty is not a function
at RelationMetadata.givenInverseSidePropertyFactory (D:\Swivel_Projects\Ignite\Project 1\backend\ignite-auth-nodejs\src\entities\Role.ts:22:43)
at RelationMetadata.buildInverseSidePropertyPath (D:\Swivel_Projects\Ignite\Project 1\backend\ignite-auth-nodejs\node_modules\src\metadata\RelationMetadata.ts:628:29)
at D:\Swivel_Projects\Ignite\Project 1\backend\ignite-auth-nodejs\node_modules\src\metadata-builder\EntityMetadataBuilder.ts:1116:26
at Array.forEach (&lt;anonymous&gt;)
at EntityMetadataBuilder.computeInverseProperties (D:\Swivel_Projects\Ignite\Project 1\backend\ignite-auth-nodejs\node_modules\src\metadata-builder\EntityMetadataBuilder.ts:1096:34)
at D:\Swivel_Projects\Ignite\Project 1\backend\ignite-auth-nodejs\node_modules\src\metadata-builder\EntityMetadataBuilder.ts:158:18
at Array.forEach (&lt;anonymous&gt;)
at EntityMetadataBuilder.build (D:\Swivel_Projects\Ignite\Project 1\backend\ignite-auth-nodejs\node_modules\src\metadata-builder\EntityMetadataBuilder.ts:157:25)
at ConnectionMetadataBuilder.buildEntityMetadatas (D:\Swivel_Projects\Ignite\Project 1\backend\ignite-auth-nodejs\node_modules\src\connection\ConnectionMetadataBuilder.ts:106:11)
at processTicksAndRejections (node:internal/process/task_queues:96:5)

答案1

得分: 1

在这里,TypeORM要求属性必须是public,因为TypeORM依赖于直接访问这些属性,但是在你的代码中,你已经将实体属性标记为private。所以可以通过修改你的代码来解决这个问题:

@Entity()
class User {
    @PrimaryColumn()
    public id: string;

    @Column({ nullable: false, length: 15 })
    public firstname: string;

    @Column({ nullable: false, length: 15 })
    public lastname: string;

    @Column({ nullable: false, unique: true, length: 25 })
    public email: string;

    @Column({ nullable: false })
    public password: string;

    @OneToMany(() => Role, (role) => role.user)
    public roles: Role[];

    // 其余的代码...
}

@Entity()
class Role {
    @PrimaryColumn()
    public id: string;

    @Column({ nullable: false })
    public role: string;

    @ManyToOne(() => User, (user) => user.roles)
    public user: User;

    // 剩余的代码...
}
英文:

Here TypeORM requires the properties to be public because TypeORM relies on direct access to the properties but in you code you have marked entity properties to private. So this can be solved by modifying your code as :

@Entity()
class User {
@PrimaryColumn()
public id: string;
@Column({ nullable: false, length: 15 })
public firstname: string;
@Column({ nullable: false, length: 15 })
public lastname: string;
@Column({ nullable: false, unique: true, length: 25 })
public email: string;
@Column({ nullable: false })
public password: string;
@OneToMany(() =&gt; Role, (role) =&gt; role.user)
public roles: Role[];
// Rest of the code...
}
@Entity()
class Role {
@PrimaryColumn()
public id: string;
@Column({ nullable: false })
public role: string;
@ManyToOne(() =&gt; User, (user) =&gt; user.roles)
public user: User;
// Remaining code...
}

huangapple
  • 本文由 发表于 2023年6月9日 14:17:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/76437679.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定