英文:
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 = "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)
答案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(() => Role, (role) => role.user)
public roles: Role[];
// Rest of the code...
}
@Entity()
class Role {
@PrimaryColumn()
public id: string;
@Column({ nullable: false })
public role: string;
@ManyToOne(() => User, (user) => user.roles)
public user: User;
// Remaining code...
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论