Советы по ручному управлению контекстом персистентности - PullRequest
3 голосов
/ 24 августа 2010

Я исследую использование JPA для моего кода доступа к данным. Я пытаюсь написать бизнес-уровень и уровень доступа к данным, чтобы он работал в веб-приложении и приложении Java SE. Поэтому я не могу использовать контекст персистентности, управляемой контейнером. Большинство моих поисков по использованию JPA показывают примеры в среде, управляемой контейнером.

В данный момент я получаю EntityManagerFactory каждый раз, когда создаю новый объект класса обслуживания. Для каждой операции (т.е. добавления, получения и т. Д.) Я открываю EntityManager, запускаю транзакцию, выполняю операции, фиксирую, а затем закрываю EntityManager и EntityManagerFactory. Я хотел бы получить преимущества от наличия управляемого персистентного контекста вне среды Java EE.

Существуют ли передовые практики, когда не используется контекст, управляемый контейнером? Существуют ли в Java EE независимые менеджеры контекста персистентности? Есть ли рекомендуемые шаблоны?

Спасибо

Al

Обновление

Спасибо всем за информацию. Все было очень полезно.

Ответы [ 4 ]

5 голосов
/ 24 августа 2010

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

В принципе вам понадобится что-то, чтобы создать EntityManager с.Я всегда использовал Spring для этого.Их документация имеет большой раздел по этому вопросу.Вы можете использовать LocalEntityManagerFactoryBean, и в этом случае разметка будет выглядеть (из вышеупомянутой документации ):

<bean id="myEmf" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
  <property name="persistenceUnitName" value="myPersistenceUnit"/>
</bean>

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

Конфигурирование вашего источника данных может быть затем выполнено с помощью специальных свойств спящего режима в единице персистентности (постоянство.xml в каталоге META-INF /):

<property name="hibernate.connection.driver_class" value="com.company.driver" />
<property name="hibernate.connection.url" value="some:jdbc@string" />
<property name="hibernate.connection.username" value="myuser" />
<property name="hibernate.connection.password" value="mypassword" />

Чтобы использовать это, если вы еще не используете Spring, вы можете просто получить экземпляр EntityManagerFactory из контекста приложения и перейти оттуда(т.е. context.getBean("myEmf")).

Больше возможностей возможно с LocalContainerEntityManagerFactoryBean, этот позволяет вам конфигурировать источник данных.В принципе, пример из документации должен работать, но я обнаружил, что когда я это сделал, мне пришлось указать поставщика персистентности Hibernate.Вам нужен файл persistence.xml, но на самом деле ему нужен только модуль персистентности по умолчанию и очень базовая конфигурация (возможно, для определения диалекта, например, если вы используете hibernate с oracle 10g):

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="myDatasource" />
    <property name="persistenceProvider">
        <bean class="org.hibernate.ejb.HibernatePersistence" />
    </property>
</bean>

В других местах есть примерывесенние документы о том, как настроить BasicDataSource из Apache dbcp , который также даст вам пул соединений.

Что касается передового опыта, JPA действительно не прост в работеза пределами полной среды сервера приложений.При настройке производительности возникают всевозможные проблемы, когда вы обнаруживаете, что слюнки над функциями Hibernate недоступны в JPA, и есть вероятность, что ваши запросы в конечном итоге не будут строго соответствовать спецификациям JPA.Если вы не используете управление контейнерами, возможно, будет гораздо проще и разумнее просто напрямую использовать API Hibernate.

4 голосов
/ 25 августа 2010

В данный момент я получаю EntityManagerFactory каждый раз, когда создаю новый экземпляр класса обслуживания.Для каждой операции (т.е. добавления, получения и т. Д.) Я открываю EntityManager, запускаю транзакцию, выполняю операции, фиксирую, а затем закрываю EntityManager и EntityManagerFactory .

. Вам, безусловно, следует НЕ открывать и закрывать EntityManagerFactory каждый раз, когда вы создаете экземпляр службы.Создание EntityManagerFactory является очень дорогой операцией и должно выполняться только один раз за время существования приложения.Просто чтобы проиллюстрировать это, вот очень простой пример, показывающий, как вы можете справиться с этим с помощью служебного класса:

public class JpaUtil {
    private JpaUtil() {}

    private static EntityManagerFactory emf = null;

    static {
        try {
            emf = Persistence.createEntityManagerFactory("MyPu");
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static EntityManager getEntityManager() {
        return emf.createEntityManager();
    }
}

Но хотя вы можете сделать его более сложным (используя некоторые ThreadLocal, см. этот пример ), это не приведет к удалению кода жизненного цикла и управления транзакциями EntityManager.

Я хотел бы получить преимущества наличия управляемого контекста персистентности вне среды Java EE.

Тогда вам понадобится какой-то контейнер для этого, и Spring станет очевидным кандидатом и может быть использован для декларативного управления транзакциями и внедрения EntityManager в бины Spring,даже в среде Java SE.

В блоге Использование JPA в Spring без ссылки на Spring точно показывает, как это сделать, используя:

  • LocalEntityManagerFactoryBean для создания EntityManagerFactory
  • JpaTransactionManager для управления транзакциями JPA
  • <tx:annotation-driven />, чтобы сообщить Spring для поиска @Transactional
  • Определение вашего бина!

И предоставляет пример файла конфигурации Spring, который поможет вам начать работу.

Ссылки

См. Также

1 голос
/ 24 августа 2010

На самом деле, существует большая поддержка для использования JPA вне сред Java EE. См:

Оба из них работают внутри и вне сред Java EE.

Как вы упоминали, за пределами обычной среды Java EE вы попадаете в «открыть EntityManager, запустить транзакцию, зафиксировать транзакцию и закрыть цикл EntityManager, который является PITA для программирования и поддерживать.

Чтобы воспользоваться преимуществами среды EE, я рекомендую использовать JPA-часть среды Spring. Документация aplenty с множеством примеров. В частности, класс JpaDaoSupport и аннотация Transactional обеспечивают большую поддержку.

Это позволяет вам делать подобные вещи без среды EE:

    import java.util.List;
    import org.springframework.orm.jpa.support.JpaDaoSupport;

    public class SpeakerDAOImpl extends JpaDaoSupport implements SpeakerDAO {

    public Speaker findSpeaker(long id) {
       return getJpaTemplate().find(Speaker.class,id);
    }

    @Transactional
    public void saveSpeaker(Speaker s) {
       getJpaTemplate().persist(s);
    }
  }

Некоторые учебные пособия, документы и т. Д.:

0 голосов
/ 10 марта 2011

Это не отвечает на ваш вопрос, но Ebean ORM использует отображение JPA (@Entity и т. Д.), Но имеет «автоматическое управление контекстом постоянства» - это означает, что вам не нужно управлять EntityManager.

Ebean не поддерживает API JPA (у него есть API «без сессии» - нет EntityManager, нет подключенных / отключенных bean-компонентов и т. Д.), Но если вы ищете простой маршрут без хлопот с управлением EntityManager, то это может быть полезно взгляд.

...