TypeORM:如何在没有加载关系的属性的情况下显式设置 ForeignKey?
Posted
技术标签:
【中文标题】TypeORM:如何在没有加载关系的属性的情况下显式设置 ForeignKey?【英文标题】:TypeORM: How to set ForeignKey explicitly without having property for loading relations? 【发布时间】:2019-08-05 20:13:48 【问题描述】:我不想创建用于将关系加载到其中的属性(如所有示例所示)。我唯一需要的是拥有一个显式外键属性,以便迁移 能够在数据库中为其创建适当的约束。最接近我需要的装饰器是@RelationId,但它仍然需要存在关系类的属性。
为了清楚起见,让我们以文档中的示例为例:
@Entity()
export class Post
@ManyToOne(type => Category)
category: Category;
@RelationId((post: Post) => post.category) // it still requires the presence of the `category` proeprty
categoryId: number;
我在这里不需要category
属性。我想拥有categoryId
属性并将其标记为外键 到Category.Id
。它应该是这样的:
@Entity()
export class Post
@ForeignKey((category: Category) => category.Id) // it's a foreign key to Category.Id
categoryId: number;
有可能吗?
【问题讨论】:
嘿,你有办法解决这个问题吗? 对不起,伙计,我在一年前改变了我的技术栈。我相信我当时没有找到解决办法。 是的,我根据 charles 解决方案找到了它。 【参考方案1】:“我需要的是有一个明确的外键属性”...
不,你不能。当你使用 @ManyToOne 装饰器时,TypeOrm 会自动创建外键属性。只需像这样将 @ManyToOne 和 @JoinColumn 装饰器组合在一起:
@ManyToOne(type => Category)
@JoinColumn( name: 'custom_field_name_if_you_want' )
category: Category;
【讨论】:
【参考方案2】:也许您可以创建和编写自己的迁移并像这样使用它:
const queryRunner = connection.createQueryRunner();
await queryRunner.createTable(new Table(
name: "question",
columns: [
name: "id",
type: "int",
isPrimary: true
,
name: "name",
type: "varchar",
]
), true);
await queryRunner.createTable(new Table(
name: "answer",
columns: [
name: "id",
type: "int",
isPrimary: true
,
name: "name",
type: "varchar",
,
name: "questionId",
isUnique: connection.driver instanceof CockroachDriver, // CockroachDB requires UNIQUE constraints on referenced columns
type: "int",
]
), true);
// clear sqls in memory to avoid removing tables when down queries executed.
queryRunner.clearSqlMemory();
const foreignKey = new TableForeignKey(
columnNames: ["questionId"],
referencedColumnNames: ["id"],
referencedTableName: "question",
onDelete: "CASCADE"
);
await queryRunner.createForeignKey("answer", foreignKey);
这段代码 sn-p 是从 orm 类型的functional test 中提取的,我认为您可以使用它在数据库上创建自己的约束。
【讨论】:
【参考方案3】:其实是可以的:
@Entity()
export class Post
// this will add categoryId
@ManyToOne(type => Category)
category: Category;
// and you can use this for accessing post.categoryId
// only column you mark with @Column decorator will be mapped to a database column
// Ref: https://typeorm.io/#/entities
categoryId: number;
添加的categoryId
不会映射到列,然后将用于显式设置 id 或访问其值,如下所示:
post.categoryId = 1;
// or
const id = post.categoryId
【讨论】:
【参考方案4】:检查这两个地方 Auth module(JwtModule.register()) 和 JWT strategy(super(...))。确保您将秘密 /secretOrKey 设置为相同的密钥。就我而言,“secret:process.env.JWT_SECRET_KEY”和“secretOrKey:process.env.JWT_SECRET_KEY”
【讨论】:
嗨@Sunny Tare,记得使用块代码格式让你的代码在你的答案中更容易阅读【参考方案5】:我最近遇到了同样的问题。 我仍然使用实体,但仅使用引用实体的主键值。
即我不查询被引用实体的数据库。
假设您的类别实体如下所示:
@Entity()
export class Category
@PrimaryGeneratedColumn()
id: number;
// ... other stuff
现在以您的代码为例。 使用外键值直接分配关系就像。
// You wish to assign category #12 to a certain post
post.category = id: 12 as Category
【讨论】:
以上是关于TypeORM:如何在没有加载关系的属性的情况下显式设置 ForeignKey?的主要内容,如果未能解决你的问题,请参考以下文章
在 TypeORM 与 GraphQL 的多对多关系上使用数据加载器,查询多对多