TypeORM postgresql 急切加载关系定义为惰性
Posted
技术标签:
【中文标题】TypeORM postgresql 急切加载关系定义为惰性【英文标题】:TypeORM postgresql eager load relationships defined as lazy 【发布时间】:2019-02-19 08:15:21 【问题描述】:我正在尝试找出解决我的 Nestjs TypeORM postgresql 应用程序中的惰性关系的最佳方法(或最佳实践方法)。
我已将实体中的一些 OneToMany 和 ManyToOne 关系定义为惰性关系,当查询其中一个实体的数组时,我发现的最佳解决方案是大量的 promise rosolving。
我的Customer
实体(customer.entity.ts):
import Column, CreateDateColumn, Entity, Index, PrimaryGeneratedColumn, UpdateDateColumn, ManyToOne, OneToMany from 'typeorm';
import IsEmail from 'class-validator';
import ReservationDate from '../reservation_date/reservation_date.entity';
@Entity()
export class Customer
@PrimaryGeneratedColumn('uuid')
id: string;
@Index()
@Column()
@IsEmail()
email: string;
@Column()
firstName: string;
@Column()
lastName: string;
@CreateDateColumn()
createDate: Date;
@UpdateDateColumn()
updateDate: Date;
@OneToMany(type => ReservationDate, reservationDate => reservationDate.customer)
reservationDates: Promise<ReservationDate[]>;
还有我的ReservationDate
实体(reservation_date.entity.ts):
import Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn, ManyToOne from 'typeorm';
import Customer from '../customer/customer.entity';
@Entity()
export class ReservationDate
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
date: Date;
@CreateDateColumn()
createDate: Date;
@UpdateDateColumn()
updateDate: Date;
@ManyToOne(type => Customer, customer => customer.reservationDates, onDelete: 'CASCADE' )
customer: Promise<Customer>;
我需要检索ReservationDate
s 的数组,并将其发送到某个地方,但我需要它来解析customer
字段(例如,急切加载该关系)。这就是“有效”:
const reservationDates: ReservationDate[] = await this.reservationDateRepository
.createQueryBuilder('reservationDate')
.leftJoinAndSelect('reservationDate.customer', 'customer')
.getMany();
// Same result as query builder above
// const reservationDates: ReservationDate[] = await this.reservationDateRepository
// .find(
// relations: ['customer'],
// take: 5
// );
console.log(reservationDates[0].car); // => Promise <pending>
console.log(reservationDates[0].__car__); // => Car id: string, owner...
// this is where it gets ugly
const reservationDatesWithResolvedRelationships = await Promise.all(
reservationDates.map(async (resDate: ReservationDate) =>
const withResolved: ReservationDateRepoObject = ...resDate ;
withResolved.customer = await resDate.customer;
return withResolved;
)
);
console.log(reservationDatesWithResolvedRelationships[0].car); // => Car id: string, owner...
// send off the JSON-like object here
我觉得应该有一种方法来进行连接并强制加载,但查询构建器或repository.find
方法似乎都没有按照我设置的方式执行此操作。
我也尝试将 lazy: true
和 eager: true
添加到实体中的关系中,但没有任何改变。
编辑:
仍然没有多少运气,但是我能够拼凑出一个伪解决方案。
private parseRaw = name => raw =>
const parsed = new ReservationDate();
Object.entries(raw).forEach(([typeKey, value]) =>
const [type, key] = typeKey.split('_');
if (type === name)
parsed[key] = value;
else
parsed[type] = parsed[type] || ;
parsed[type][key] = value;
);
return parsed;
;
let reservationDates: ReservationDate[] = (await this.reservationDateRepository
.createQueryBuilder('reservationDate')
.leftJoinAndSelect('reservationDate.customer', 'customer')
.limit(5)
.getRawMany()).map(this.parseRaw('reservationDate'));
超级丑陋的 hack,但它将原始的 snake_case
db 结果转换为我需要发送的 camelCase
json 对象...
【问题讨论】:
【参考方案1】:你需要使用find()
来实现预加载,
仅当您使用 find* 方法时,急切关系才有效。如果您使用 QueryBuilder 急切关系被禁用并且必须使用 leftJoinAndSelect 来加载关系。 Eager 关系只能在关系的一侧使用,在关系的两侧都使用 eager: true 是不允许的。
Docs here
【讨论】:
以上是关于TypeORM postgresql 急切加载关系定义为惰性的主要内容,如果未能解决你的问题,请参考以下文章