Когда и зачем использовать em.clear() в МикроОрм

Я немного запутался в том, что em.clear() делает в MikroOrm или любом подобном менеджере сущностей. https://mikro-orm.io/docs/entity-manager ссылка для clear() метод.

Кажется, некоторые из ответов stackoverflow относительно общего EntityManager сказали, что мне нужно вызывать clear() после каждого persist/remove and flush, чтобы избежать проблем с памятью.

Чтобы сделать этот вопрос более конкретным для моего случая, предположительно я создаю конечную точку Graphql в своем приложении. Есть некоторые общие функции CRUD для вызова пользователями, каждая функция создаст MikroOrm entity, используя некоторые функции MikroOrm, такие как findOne() и т. д., для выполнения некоторой общей операции CRUD в базе данных.

Означает ли это, что мне нужно вызывать clear() каждый раз после persist/remove and flush (если есть какая-то операция CUD) и даже только читать данные? А что произойдет, если я не вызову этот метод?


person Yunhai    schedule 08.09.2020    source источник


Ответы (2)


em.clear() предназначен для тестирования, поэтому вы можете имитировать несколько независимых запросов с помощью одного экземпляра EM:

const book1 = await em.findOne(Book, 1); // now book 1 will be loaded
const book2 = await em.findOne(Book, 1); // as book 1 is already loaded, this won't query the db
expect(book1).toBe(book2); // and we will get identity here
em.clear(); // but when we clear the identity map
const book3 = await em.findOne(Book, 1); // this will query the db as the state is now gone
expect(book1).not.toBe(book3); // and identity is gone

Вы можете добиться того же, используя em.fork(), используя несколько EM вместо одного.

Память должна освобождаться автоматически при сборке мусора, вам не нужен метод em.clear() в обычном (прикладном) коде. Код вашего приложения должен использовать либо вспомогательную функцию RequestContext, либо разветвление вручную (см. https://mikro-orm.io/docs/identity-map). После завершения запроса не должно быть ссылок на этот старый контекст, и он должен быть удален сборщиком мусора (но имейте в виду, что это происходит недетерминировано, например, когда JS-движку так хочется :]).

person Martin Adámek    schedule 08.09.2020
comment
Большое спасибо, Ваша ссылка также помогает мне понять, почему RequestContext необходим во время установки. Хотя я знал, что ты создатель библиотеки :p - person Yunhai; 08.09.2020

Есть 2 метода, которые мы должны сначала описать, чтобы понять, как работает сохранение в MikroORM: em.persist() и em.flush().

em.persist(entity, flush?: boolean) используется для обозначения новых объектов для сохранения в будущем. Это сделает сущность управляемой данным EntityManager, и после вызова сброса она будет записана в базу данных. Второй логический параметр может использоваться для немедленного вызова сброса. Его значение по умолчанию настраивается с помощью опции autoFlush.

Чтобы понять flush, давайте сначала определим, что такое управляемый объект: объект является управляемым, если он получен из базы данных (через em.find(), em.findOne() или через другой управляемый объект) или зарегистрирован как новый через em.persist().

em.flush() будет проходить через все управляемые объекты, вычислять соответствующие наборы изменений и выполнять соответствующие запросы к базе данных. Поскольку сущность, загруженная из базы данных, становится управляемой автоматически, вам не нужно вызывать для них persist, и для их обновления достаточно flush.

const book = await orm.em.findOne(Book, 1);
book.title = 'How to persist things...';

// no need to persist `book` as its already managed by the EM
await orm.em.flush();
person fyn matt 881    schedule 08.09.2020
comment
это кажется неуместным для моего вопроса, но спасибо за некоторую информацию о сохранении и сбросе. - person Yunhai; 08.09.2020