Skip to content

Commit

Permalink
feat(core): respect load strategy specified in property definition
Browse files Browse the repository at this point in the history
Closes #2803
  • Loading branch information
B4nan committed Feb 21, 2022
1 parent ffe6bd8 commit 1a6b4b2
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 3 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/EntityManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -985,7 +985,7 @@ export class EntityManager<D extends IDatabaseDriver = IDatabaseDriver> {

return ret.map(field => {
// force select-in strategy when populating all relations as otherwise we could cause infinite loops when self-referencing
field.strategy = options.populate === true ? LoadStrategy.SELECT_IN : (options.strategy ?? field.strategy ?? this.config.get('loadStrategy'));
field.strategy = options.populate === true ? LoadStrategy.SELECT_IN : (options.strategy ?? field.strategy);
return field;
});
}
Expand Down
14 changes: 12 additions & 2 deletions packages/core/src/entity/EntityLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export class EntityLoader {
p.field = f;
p.children = p.children || [];
const prop = this.metadata.find(entityName)!.properties[f];
p.strategy ??= prop.strategy;
p.children.push(this.expandNestedPopulate(prop.type, parts, p.strategy, p.all));
});

Expand Down Expand Up @@ -237,8 +238,8 @@ export class EntityLoader {

if (prop.reference === ReferenceType.ONE_TO_ONE && !prop.owner && populate.strategy !== LoadStrategy.JOINED && !this.em.config.get('autoJoinOneToOneOwner')) {
children.length = 0;
children.push(...entities);
fk = meta.properties[prop.mappedBy].name;
children.push(...this.filterByReferences(entities, prop.name, options.refresh));
}

if (children.length === 0) {
Expand Down Expand Up @@ -461,6 +462,15 @@ export class EntityLoader {
return children.filter(e => !(e[field] as AnyEntity).__helper!.__initialized).map(e => Reference.unwrapReference(e[field]));
}

private filterByReferences<T extends AnyEntity<T>>(entities: T[], field: keyof T, refresh: boolean): T[] {
/* istanbul ignore next */
if (refresh) {
return entities;
}

return entities.filter(e => !(e[field] as AnyEntity)?.__helper?.__initialized);
}

private lookupAllRelationships<T>(entityName: string): PopulateOptions<T>[] {
const ret: PopulateOptions<T>[] = [];
const meta = this.metadata.find(entityName)!;
Expand Down Expand Up @@ -499,7 +509,7 @@ export class EntityLoader {
} else {
ret.push({
field: prefixed,
strategy: strategy ?? prop.strategy ?? this.em.config.get('loadStrategy'),
strategy: strategy ?? prop.strategy,
});
}
});
Expand Down
65 changes: 65 additions & 0 deletions tests/issues/GH2803.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Collection, Entity, LoadStrategy, ManyToOne, MikroORM, OneToMany, PrimaryKey, Property } from '@mikro-orm/core';
import type { SqliteDriver } from '@mikro-orm/sqlite';
import { mockLogger } from '../helpers';

@Entity()
export class Book {

@PrimaryKey()
id!: number;

@Property()
name?: string;

@OneToMany({
// eslint-disable-next-line @typescript-eslint/no-use-before-define
entity: () => Tag,
mappedBy: t => t.book,
strategy: LoadStrategy.JOINED,
})
tags = new Collection<Tag>(this);

}

@Entity()
export class Tag {

@PrimaryKey()
id!: number;

@ManyToOne(() => Book)
book!: Book;

}

describe('GH issue 2803', () => {

let orm: MikroORM<SqliteDriver>;

beforeAll(async () => {
orm = await MikroORM.init({
type: 'sqlite',
dbName: ':memory:',
entities: [Book, Tag],
});
await orm.getSchemaGenerator().createSchema();
});

afterAll(async () => {
await orm.close(true);
});

test(`load strategy defined on property level is respected`, async () => {
const b = orm.em.create(Book, {
name: 'b',
tags: [{}, {}, {}],
});
await orm.em.fork().persist(b).flush();

const mock = mockLogger(orm, ['query']);
const ret = await orm.em.find(Book, {}, { populate: ['tags'] });
expect(ret[0].tags).toHaveLength(3);
expect(mock).toBeCalledTimes(1);
});

});

0 comments on commit 1a6b4b2

Please sign in to comment.