Внедрение EntityManager Vs. EntityManagerFactory - PullRequest
68 голосов
/ 21 августа 2009

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

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

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

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

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

Ответы [ 4 ]

51 голосов
/ 21 августа 2009

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

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

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

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

Аргументом для введения ЭМП является то, что это хорошая практика над всеми своими всегда хорошо иметь ручку к завод.

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

24 голосов
/ 21 августа 2009

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

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

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

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

9 голосов
/ 21 августа 2009

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

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

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

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

Продолжение:

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

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

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

Другое продолжение:

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

6 голосов
/ 21 августа 2009

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

...