Skip to content

Commit

Permalink
fix(core): register entity to identity map as early as possible
Browse files Browse the repository at this point in the history
Closes #2777
  • Loading branch information
B4nan committed Feb 18, 2022
1 parent 497ea78 commit d8f3613
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 4 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/EntityManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { AssignOptions, EntityLoaderOptions, EntityRepository, IdentifiedRe
import { EntityAssigner, EntityFactory, EntityLoader, EntityValidator, Reference } from './entity';
import { UnitOfWork } from './unit-of-work';
import type { CountOptions, DeleteOptions, EntityManagerType, FindOneOptions, FindOneOrFailOptions, FindOptions, IDatabaseDriver, InsertOptions, LockOptions, UpdateOptions, GetReferenceOptions, EntityField } from './drivers';
import type { AnyEntity, AutoPath, Dictionary, EntityData, EntityDictionary, EntityDTO, EntityMetadata, EntityName, FilterDef, FilterQuery, GetRepository, Loaded, New, Populate, PopulateOptions, Primary, RequiredEntityData } from './typings';
import type { AnyEntity, AutoPath, Dictionary, EntityData, EntityDictionary, EntityDTO, EntityMetadata, EntityName, FilterDef, FilterQuery, GetRepository, Loaded, Populate, PopulateOptions, Primary, RequiredEntityData } from './typings';
import { FlushMode, LoadStrategy, LockMode, PopulateHint, ReferenceType, SCALAR_TYPES } from './enums';
import type { TransactionOptions } from './enums';
import type { MetadataStorage } from './metadata';
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/entity/EntityFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ export class EntityFactory {
entity.__helper!.__managed = true;
entity.__helper!.__schema = this.driver.getSchemaName(meta, options);

if (meta.selfReferencing && !options.newEntity) {
if (options.merge && !options.newEntity) {
this.hydrator.hydrateReference(entity, meta, data, this, options.convertCustomTypes, this.driver.getSchemaName(meta, options));
this.unitOfWork.registerManaged(entity);
}
Expand All @@ -218,7 +218,7 @@ export class EntityFactory {
private findEntity<T>(data: EntityData<T>, meta: EntityMetadata<T>, options: FactoryOptions): T | undefined {
const schema = this.driver.getSchemaName(meta, options);

if (!meta.compositePK && !meta.properties[meta.primaryKeys[0]]?.customType) {
if (!meta.compositePK && !meta.getPrimaryProps()[0]?.customType) {
return this.unitOfWork.getById<T>(meta.name!, data[meta.primaryKeys[0] as string] as Primary<T>, schema);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ describe('single table inheritance in mysql', () => {
expect(Object.keys(users[0])).toEqual(['id', 'firstName', 'lastName', 'type', 'employeeProp']);
expect(Object.keys(users[1])).toEqual(['id', 'firstName', 'lastName', 'type', 'employeeProp']);
expect(Object.keys(users[2])).toEqual(['id', 'firstName', 'lastName', 'type', 'managerProp']);
expect(Object.keys(users[3])).toEqual(['firstName', 'lastName', 'type', 'ownerProp', 'favouriteEmployee', 'favouriteManager', 'managerProp', 'id']);
expect(Object.keys(users[3])).toEqual(['id', 'firstName', 'lastName', 'type', 'ownerProp', 'favouriteEmployee', 'favouriteManager', 'managerProp']);

expect([...orm.em.getUnitOfWork().getIdentityMap().keys()]).toEqual(['BaseUser2-4', 'BaseUser2-1', 'BaseUser2-2', 'BaseUser2-3']);

Expand Down
103 changes: 103 additions & 0 deletions tests/issues/GH2777.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { Entity, LoadStrategy, ManyToOne, MikroORM, OneToOne, PrimaryKey, Property, wrap } from '@mikro-orm/core';

@Entity()
export class Image {

@PrimaryKey()
id!: number;

// eslint-disable-next-line @typescript-eslint/no-use-before-define
@OneToOne(() => Customer)
customer!: any;

}

@Entity()
export class Product {

@PrimaryKey()
id!: number;

@Property()
title!: string;

@ManyToOne(() => Image, {
strategy: LoadStrategy.JOINED,
eager: true,
nullable: true,
})
image?: Image;

// eslint-disable-next-line @typescript-eslint/no-use-before-define
@OneToOne(() => Customer)
customer!: any;

}

@Entity()
export class Comment {

@PrimaryKey()
id!: number;

@Property()
title!: string;

// eslint-disable-next-line @typescript-eslint/no-use-before-define
@OneToOne(() => Customer)
customer!: any;

}

@Entity()
export class Customer {

@PrimaryKey()
id!: number;

@Property()
name!: string;

@OneToOne(() => Product, product => product.customer, { eager: true })
product!: Product;

@OneToOne(() => Comment, comment => comment.customer, { eager: true })
comment!: Comment;

}

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

let orm: MikroORM;

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

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

test(`GH issue 2777`, async () => {
const c = new Customer();
c.comment = new Comment();
c.comment.title = 'c';
c.product = new Product();
c.product.title = 't';
c.product.image = new Image();
c.product.image.customer = c;
c.name = 'f';
await orm.em.fork().persistAndFlush(c);
const ret = await orm.em.find(Customer, {});
expect(ret[0]).toBe(ret[0].product.image!.customer);
expect(wrap(ret[0].product).isInitialized()).toBe(true);
expect(wrap(ret[0].product.image).isInitialized()).toBe(true);
expect(wrap(ret[0].product.image!.customer).isInitialized()).toBe(true);
});

});

0 comments on commit d8f3613

Please sign in to comment.