diff --git a/ROADMAP.md b/ROADMAP.md index c452579760c0..6bbe71261c9a 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -39,7 +39,7 @@ discuss specifics. - [x] Require TS 3.7 or newer - [x] Split into multiple packages (core, driver packages, TS support, SQL support, CLI) - [ ] Drop default value for db `type` (currently defaults to `mongodb`) -- [ ] Remove `autoFlush` option +- [x] Remove `autoFlush` option - [ ] Remove `IdEntity/UuidEntity/MongoEntity` interfaces - [ ] Rename `wrappedReference` to `reference` (keep `wrappedReference` supported) - [ ] Use `bigint` type natively in `BigIntType` diff --git a/docs/docs/upgrading-v3-to-v4.md b/docs/docs/upgrading-v3-to-v4.md index c0df9e4627fd..e3879b0d81ff 100644 --- a/docs/docs/upgrading-v3-to-v4.md +++ b/docs/docs/upgrading-v3-to-v4.md @@ -21,3 +21,11 @@ TODO multiple packages ## SqlEntityManager and MongoEntityManager TODO QB getter, knex getter, aggregate... + +## `autoFlush` option has been removed + +The `flush` parameter of `persist()` and `remove()` methods is still there, but you +should prefer to call `em.flush()` explicitly. + +Also `persistLater()` and `removeLater()` methods are deprecated. Use `persist()` or +`remove` respectively. diff --git a/packages/core/src/EntityManager.ts b/packages/core/src/EntityManager.ts index df64535887de..c6d8f40725b6 100644 --- a/packages/core/src/EntityManager.ts +++ b/packages/core/src/EntityManager.ts @@ -374,12 +374,18 @@ export class EntityManager { * Tells the EntityManager to make an instance managed and persistent. You can force flushing via second parameter. * The entity will be entered into the database at or before transaction commit or as a result of the flush operation. */ - persist(entity: AnyEntity | AnyEntity[], flush = this.config.get('autoFlush')): void | Promise { - if (flush) { - return this.persistAndFlush(entity); + persist(entity: AnyEntity | AnyEntity[], flush?: false): void; + persist(entity: AnyEntity | AnyEntity[], flush: true): Promise; + persist(entity: AnyEntity | AnyEntity[], flush = false): void | Promise { + const entities = Utils.asArray(entity); + + for (const ent of entities) { + this.getUnitOfWork().persist(ent); } - this.persistLater(entity); + if (flush) { + return this.flush(); + } } /** @@ -387,31 +393,31 @@ export class EntityManager { * Equivalent to `em.persistLater(e) && em.flush()`. */ async persistAndFlush(entity: AnyEntity | AnyEntity[]): Promise { - this.persistLater(entity); + this.persist(entity); await this.flush(); } /** * Tells the EntityManager to make an instance managed and persistent. * The entity will be entered into the database at or before transaction commit or as a result of the flush operation. + * + * @deprecated use `persist()` */ persistLater(entity: AnyEntity | AnyEntity[]): void { - const entities = Utils.asArray(entity); - - for (const ent of entities) { - this.getUnitOfWork().persist(ent); - } + this.persist(entity); } /** * Removes an entity instance or all entities matching your `where` query. When deleting entity by instance, you * will need to flush your changes. You can force flushing via third parameter. */ - remove>(entityName: EntityName, where: FilterQuery | T, flush = this.config.get('autoFlush')): void | Promise { + remove>(entityName: EntityName, where: FilterQuery | T, flush?: false): void; + remove>(entityName: EntityName, where: FilterQuery | T, flush: true): Promise; + remove>(entityName: EntityName, where: FilterQuery | T, flush = false): void | Promise { entityName = Utils.className(entityName); if (Utils.isEntity(where)) { - const ret = this.removeEntity(where, flush); + const ret = this.removeEntity(where, flush as true); return ret ? ret.then(() => 1) : ret; } @@ -422,12 +428,14 @@ export class EntityManager { * Removes an entity instance. You can force flushing via second parameter. * A removed entity will be removed from the database at or before transaction commit or as a result of the flush operation. */ - removeEntity>(entity: T, flush = this.config.get('autoFlush')): void | Promise { + removeEntity>(entity: T, flush?: false): void; + removeEntity>(entity: T, flush: true): Promise; + removeEntity>(entity: T, flush = false): void | Promise { + this.getUnitOfWork().remove(entity); + if (flush) { - return this.removeAndFlush(entity); + return this.flush(); } - - this.removeLater(entity); } /** @@ -442,6 +450,8 @@ export class EntityManager { /** * Removes an entity instance. * A removed entity will be removed from the database at or before transaction commit or as a result of the flush operation. + * + * @deprecated use `removeEntity()` */ removeLater(entity: AnyEntity): void { this.getUnitOfWork().remove(entity); diff --git a/packages/core/src/entity/EntityRepository.ts b/packages/core/src/entity/EntityRepository.ts index 17e1abdeb8a5..169d967baafb 100644 --- a/packages/core/src/entity/EntityRepository.ts +++ b/packages/core/src/entity/EntityRepository.ts @@ -8,14 +8,19 @@ export class EntityRepository> { constructor(protected readonly em: EntityManager, protected readonly entityName: EntityName) { } - persist(entity: AnyEntity | AnyEntity[], flush = this.em.config.get('autoFlush')): void | Promise { - return this.em.persist(entity, flush); + persist(entity: AnyEntity | AnyEntity[], flush?: false): void; + persist(entity: AnyEntity | AnyEntity[], flush: true): Promise; + persist(entity: AnyEntity | AnyEntity[], flush = false): void | Promise { + return this.em.persist(entity, flush as true); } async persistAndFlush(entity: AnyEntity | AnyEntity[]): Promise { await this.em.persistAndFlush(entity); } + /** + * @deprecated use `persist()` + */ persistLater(entity: AnyEntity | AnyEntity[]): void { this.em.persistLater(entity); } @@ -50,14 +55,19 @@ export class EntityRepository> { return this.em.find(this.entityName, {}, populate as string[], orderBy, limit, offset); } - remove(where: T | FilterQuery, flush = this.em.config.get('autoFlush')): void | Promise { - return this.em.remove(this.entityName, where, flush); + remove(where: T | FilterQuery, flush?: false): void; + remove(where: T | FilterQuery, flush: true): Promise; + remove(where: T | FilterQuery, flush = false): void | Promise { + return this.em.remove(this.entityName, where, flush as true); } async removeAndFlush(entity: AnyEntity): Promise { await this.em.removeAndFlush(entity); } + /** + * @deprecated use `remove()` + */ removeLater(entity: AnyEntity): void { this.em.removeLater(entity); } diff --git a/packages/core/src/utils/Configuration.ts b/packages/core/src/utils/Configuration.ts index 0e6967e32781..3c1937ef7e2d 100644 --- a/packages/core/src/utils/Configuration.ts +++ b/packages/core/src/utils/Configuration.ts @@ -26,7 +26,6 @@ export class Configuration { disableDynamicFileAccess: false, tsConfigPath: process.cwd() + '/tsconfig.json', }, - autoFlush: false, strict: false, // eslint-disable-next-line no-console logger: console.log.bind(console), @@ -306,7 +305,6 @@ export interface MikroORMOptions ex disableDynamicFileAccess?: boolean; tsConfigPath?: string; }; - autoFlush: boolean; type: keyof typeof Configuration.PLATFORMS; driver?: { new (config: Configuration): D }; driverOptions: Dictionary; diff --git a/tests/EntityManager.mongo.test.ts b/tests/EntityManager.mongo.test.ts index 1fda4118f03d..d8d4c02e3f65 100644 --- a/tests/EntityManager.mongo.test.ts +++ b/tests/EntityManager.mongo.test.ts @@ -39,9 +39,9 @@ describe('EntityManagerMongo', () => { book3.publisher = publisherRef; const repo = orm.em.getRepository(Book); - repo.persistLater(book1); - repo.persistLater(book2); - repo.persistLater(book3); + repo.persist(book1); + repo.persist(book2); + repo.persist(book3); await repo.flush(); orm.em.clear(); @@ -296,8 +296,8 @@ describe('EntityManagerMongo', () => { const author2 = new Author('name2', 'email2'); const author3 = new Author('name3', 'email3'); const repo = orm.em.getRepository(Author) as AuthorRepository; - repo.persistLater(author); - repo.persistLater(author2); + repo.persist(author); + repo.persist(author2); await repo.removeAndFlush(author); expect(Object.keys(orm.em.getUnitOfWork().getIdentityMap())).toEqual([`Author-${author2.id}`]); author2.name = 'lol'; @@ -1346,7 +1346,7 @@ describe('EntityManagerMongo', () => { const b1 = new Book('b1', author); const b2 = new Book('b2', author); const b3 = new Book('b3', author); - orm.em.persistLater([b1, b2, b3]); + orm.em.persist([b1, b2, b3]); await orm.em.flush(); orm.em.clear(); @@ -1618,7 +1618,7 @@ describe('EntityManagerMongo', () => { Object.assign(book, { tags: ['0000007b5c9c61c332380f78', tag] }); expect(book.tags).not.toBeInstanceOf(Collection); expect(book.tags).toEqual(['0000007b5c9c61c332380f78', tag]); - expect(() => orm.em.persistLater(book)).toThrowError(`Entity of type BookTag expected for property Book.tags, '0000007b5c9c61c332380f78' of type string given. If you are using Object.assign(entity, data), use wrap(entity).assign(data, { em }) instead.`); + expect(() => orm.em.persist(book)).toThrowError(`Entity of type BookTag expected for property Book.tags, '0000007b5c9c61c332380f78' of type string given. If you are using Object.assign(entity, data), use wrap(entity).assign(data, { em }) instead.`); wrap(book).assign({ tags: ['0000007b5c9c61c332380f78', tag] }, { em: orm.em }); expect(book.tags).toBeInstanceOf(Collection); diff --git a/tests/EntityRepository.test.ts b/tests/EntityRepository.test.ts index 2de488c830b3..1719df734afd 100644 --- a/tests/EntityRepository.test.ts +++ b/tests/EntityRepository.test.ts @@ -25,7 +25,7 @@ const methods = { nativeUpdate: jest.fn(), nativeDelete: jest.fn(), aggregate: jest.fn(), - config: new Configuration({ autoFlush: true } as any, false), + config: new Configuration({} as any, false), }; const Mock = jest.fn(() => methods as any); const em = new Mock(); @@ -41,7 +41,7 @@ describe('EntityRepository', () => { repo.getReference('bar'); expect(methods.getReference.mock.calls[0]).toEqual([Publisher, 'bar', false]); const e = Object.create(Publisher.prototype); - await repo.persist(e, false); + await repo.persist(e); expect(methods.persist.mock.calls[0]).toEqual([e, false]); await repo.persistAndFlush(e); expect(methods.persistAndFlush.mock.calls[0]).toEqual([e]); @@ -57,7 +57,7 @@ describe('EntityRepository', () => { expect(methods.findOneOrFail.mock.calls[0]).toEqual([Publisher, 'bar', [], undefined]); await repo.createQueryBuilder(); expect(methods.createQueryBuilder.mock.calls[0]).toEqual([Publisher, undefined]); - await repo.remove('bar'); + await repo.remove('bar', true); expect(methods.remove.mock.calls[0]).toEqual([Publisher, 'bar', true]); const entity = {} as AnyEntity; await repo.removeAndFlush(entity); diff --git a/tests/issues/GH486.test.ts b/tests/issues/GH486.test.ts index e4b64a866db5..8ef27fe45e4d 100644 --- a/tests/issues/GH486.test.ts +++ b/tests/issues/GH486.test.ts @@ -1,5 +1,5 @@ -import { Entity, PrimaryKey, Property, OneToMany, MikroORM, ReflectMetadataProvider, Collection, ManyToOne } from '../../lib'; -import { PostgreSqlDriver } from '../../lib/drivers/PostgreSqlDriver'; +import { Entity, PrimaryKey, Property, OneToMany, MikroORM, ReflectMetadataProvider, Collection, ManyToOne } from '@mikro-orm/core'; +import { PostgreSqlDriver } from '@mikro-orm/postgresql'; @Entity() class A { @@ -7,7 +7,7 @@ class A { @PrimaryKey() id!: number; - @OneToMany(() => B, b => b.a) + @OneToMany('B', 'a') bs = new Collection(this); @Property()