TypeORM多主键关联时忽略指定JoinColumn的问题求助
我有一个名为packs的实体,包含两个主键:idpack(自增主键)和idproducto,实体代码如下:
import { CreateDateColumn, Entity, JoinColumn, OneToMany, PrimaryColumn, PrimaryGeneratedColumn, } from 'typeorm'; import { productospack } from './productospack.entity'; @Entity({ schema: 'sch_main', name: 'packs', }) export class packs { @PrimaryGeneratedColumn() idpack: number; @PrimaryColumn('int') idproducto: number; @CreateDateColumn() creationdate: Date; @OneToMany(() => productospack, (productpack) => productpack.pack) @JoinColumn({ name: 'idpack' }) productos: productospack[]; }
该实体与productospack实体存在OneToMany关联,productospack实体代码如下:
import { Column, Entity, JoinColumn, ManyToOne, PrimaryGeneratedColumn, } from 'typeorm'; import { packs } from './pack.entity'; @Entity({ schema: 'sch_main', name: 'productospack', }) export class productospack { @PrimaryGeneratedColumn() idproductopack: number; @Column('int') idpack: number; @Column('int') idproducto: number; @Column('int') productquantity: number; @ManyToOne(() => packs, (pack) => pack.productos) @JoinColumn({ name: 'idpack' }) pack: packs; }
我期望查询packs实体时,TypeORM仅通过idpack字段关联productospack表,但实际执行查询时,TypeORM却同时使用idpack和idproducto两个主键进行关联:
INNER JOIN PackProduct ON PackProduct.idpack = Pack.idpack AND PackProduct.idpack = Pack.idproduct
这导致了无效的关联结果,我需要仅通过idpack进行关联。使用的是TypeORM ^0.3.19版本与PostgreSQL数据库,也曾尝试在关联的反向端明确定义关联列,但行为一致。
这不是Bug,是TypeORM处理复合主键实体关联时的默认行为:当关联的目标实体拥有复合主键时,TypeORM会自动使用所有主键字段构建关联条件,以此保证关联的唯一性。即使你在@JoinColumn中指定了单个字段,它仍会默认补充其他主键字段的关联条件。
另外,你在packs实体的@OneToMany装饰器上添加@JoinColumn的操作是冗余的——@JoinColumn应该用于拥有外键的ManyToOne端,OneToMany端只需指定反向关联即可,多余的@JoinColumn反而会干扰TypeORM的关联逻辑推断。
要让TypeORM仅通过idpack字段关联,需要做两处修改:
- 移除
packs实体中@OneToMany上的@JoinColumn - 在
productospack实体的@JoinColumn中显式指定referencedColumnName为idpack
修改后的代码如下:
修改后的packs实体
import { CreateDateColumn, Entity, OneToMany, PrimaryColumn, PrimaryGeneratedColumn, } from 'typeorm'; import { productospack } from './productospack.entity'; @Entity({ schema: 'sch_main', name: 'packs', }) export class packs { @PrimaryGeneratedColumn() idpack: number; @PrimaryColumn('int') idproducto: number; @CreateDateColumn() creationdate: Date; // 移除@JoinColumn,仅保留反向关联指向 @OneToMany(() => productospack, (productpack) => productpack.pack) productos: productospack[]; }
修改后的productospack实体
import { Column, Entity, JoinColumn, ManyToOne, PrimaryGeneratedColumn, } from 'typeorm'; import { packs } from './pack.entity'; @Entity({ schema: 'sch_main', name: 'productospack', }) export class productospack { @PrimaryGeneratedColumn() idproductopack: number; @Column('int') idpack: number; @Column('int') idproducto: number; @Column('int') productquantity: number; @ManyToOne(() => packs, (pack) => pack.productos) // 明确指定外键列关联到packs的idpack主键字段 @JoinColumn({ name: 'idpack', referencedColumnName: 'idpack' }) pack: packs; }
这样修改后,TypeORM生成的关联SQL就只会使用idpack字段进行匹配,不会再自动添加idproducto的关联条件。
内容的提问来源于stack exchange,提问作者Omar Pintado

