Внедрение EntityManager Vs. EntityManagerFactory

Длинный вопрос, пожалуйста, потерпите меня.

Мы используем Spring + JPA для веб-приложения. Моя команда обсуждает введение EntityManagerFactory в GenericDAO (DAO, основанное на Generics, что-то в строках, предоставленных APPFUSE, мы по какой-то причине не используем JpaDaosupport) вместо введения EntityManager. Мы используем «постоянство, управляемое приложением».

Аргументы против введения EntityManagerFactory заключаются в том, что он слишком тяжелый и поэтому не требуется, EntityManager делает то, что нам нужно. Кроме того, поскольку Spring будет создавать новый экземпляр DAO для каждого веб-запроса (я сомневаюсь в этом), проблем с параллелизмом не возникнет, поскольку один и тот же экземпляр EntityManager используется двумя потоками.

Аргументом в пользу внедрения EFM является то, что всегда полезно иметь дескриптор для фабрики.

Я не уверен, какой подход лучше, может кто-нибудь просветить меня?


person SB.    schedule 21.08.2009    source источник
comment
Я также понимаю, что, поскольку Spring внедряет EntityManager, это постоянство, управляемое контейнером, а также что Spring делает Entitymanager потокобезопасным. SB   -  person SB.    schedule 21.08.2009


Ответы (4)


Плюсы и минусы внедрения EntityManagerFactory и EntityManager описаны в документации Spring здесь, я не уверен, что смогу улучшить это.

Сказав это, в вашем вопросе есть некоторые моменты, которые следует прояснить.

... Spring будет создавать новый экземпляр DAO для каждого веб-запроса ...

Это не так. Если ваш DAO является компонентом Spring, то это синглтон, если вы не сконфигурируете его иначе с помощью атрибута scope в определении компонента. Создавать экземпляр DAO для каждого запроса было бы безумием.

Аргументом в пользу внедрения EMF является то, что всегда полезно иметь привязку к фабрике.

Этот аргумент не выдерживает никакой критики. Общая передовая практика гласит, что объект должен быть внедрен с минимальным количеством участников, необходимых для выполнения его работы.

person skaffman    schedule 21.08.2009
comment
Если вы не можете улучшить их объяснение, не могли бы вы его перефразировать? В этом документе много всего, и я не совсем понимаю, где это прописано. Кроме того, всегда лучше иметь ответ, который может стоять сам по себе, и людям не нужно переходить по ссылке, чтобы увидеть ваш полный ответ. - person Jasper; 06.11.2019

Я записываю то, что наконец собрал. Из раздела "Реализация DAO на основе простого JPA" в справочнике Spring:

Хотя экземпляры EntityManagerFactory являются потокобезопасными, экземпляры EntityManager - нет. Внедренный JPA EntityManager ведет себя как EntityManager, полученный из среды JNDI сервера приложений, как определено в спецификации JPA. Он делегирует все вызовы текущему транзакционному EntityManager, если таковой имеется; в противном случае он возвращается к вновь созданному EntityManager для каждой операции, что фактически делает его использование потокобезопасным.

Это означает, что согласно спецификациям JPA экземпляры EntityManager не являются потокобезопасными, но если Spring обрабатывает их, они становятся потокобезопасными.

Если вы используете Spring, лучше внедрить EntityManager вместо EntityManagerFactory.

person SB.    schedule 21.08.2009

Я думаю, что это уже хорошо освещено, но лишь для того, чтобы подчеркнуть несколько моментов.

  • Если DAO вводится Spring, по умолчанию является одноэлементным. Вы должны явно установить для области видимость прототипа, чтобы каждый раз создавать новый экземпляр.

  • Менеджер сущностей, введенный @PersistenceContext , является потокобезопасным.

При этом у меня были некоторые проблемы с одноэлементным DAO в моем многопоточном приложении. В итоге я сделал DAO инстансированным компонентом, и это решило проблему. Итак, хотя документация может сказать одно, вы, вероятно, захотите тщательно протестировать свое приложение.

Последующие действия:

Я думаю, что часть моей проблемы в том, что я использую

@PersistenceContext(unitName = "unit",
    type = PersistenceContextType.EXTENDED)

Если вы используете PersistenceContextType.EXTENDED, имейте в виду, что вы должны, если я правильно понимаю, вручную закрыть транзакцию. Дополнительную информацию см. В этой теме.

Еще одно продолжение:

Использование экземпляра DAO - крайне плохая идея. Каждый экземпляр DAO будет иметь свой собственный кеш постоянства, и изменения в одном кэше не будут распознаваться другими компонентами DAO. Простите за плохой совет.

person James McMahon    schedule 21.08.2009

Я обнаружил, что установка аннотации @Repository Spring в наших DAO и наличие EntityManager под управлением Spring и внедрение аннотации @PersistenceContext - это наиболее удобный способ заставить все работать плавно. Вы получаете выгоду от потоковой безопасности общего EntityManager и преобразования исключений. По умолчанию общий EntityManager будет управлять транзакциями, если вы, например, объедините несколько DAO из менеджера. В конце концов вы обнаружите, что ваши DAO станут анемичными.

person Gaël Marziou    schedule 21.08.2009