英文:
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...
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论