2010-11-01 2 views
4

У меня есть пара вопросов относительно использования диспетчера сущностей в среде JavaSE.JPA 2 - Использование EntityManager в JavaSE - несколько вопросов

Я использую шаблон репозитория для выполнения операций CRUD в базе данных. Там будет базовый класс хранилище так:

public class Repository<T> implements IRepository<T> { 

    private EntityManager em; 
    private String persistenceUnitName; 

    public Repository(String persistenceUnitName) { 
     this.persistenceUnitName = persistenceUnitName; 
    } 

    @Override 
    public T find(Class<T> type, Object id) { 
     return em.find(type, id); 
    } 

    private EntityManager getEntityManager() { 
     if (this.em == null) { 
      EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnitName); 

      em = emf.createEntityManager(); 
     } 

     return em; 
    } 
    ... 
    ... 
} 

Я тогда есть классы, как EmployeeRepository, которые унаследуют Repository. Эти классы репозитория будут созданы на моем уровне обслуживания.

Это хороший способ инициализации менеджера объектов? Я начинаю думать, что это не так - похоже, у вас должен быть только один менеджер сущностей на единицу персистентности? Где, как в этом случае, у вас будет менеджер сущности для каждого созданного вами репозитория ... Как бы вы поделились тем, что у вас есть только один менеджер сущностей на единицу персистентности? Кроме того, я заметил, что у фабричных менеджеров и методов фабричного менеджера есть метод close - когда их следует называть? На сервере прекращается событие?

Если вы знаете какие-либо хорошие источники об использовании JPA в JavaSE, я был бы признателен за информацию.

Спасибо!

ответ

3

Практически. Вам нужно всего лишь одно EntityManagerFactory для единицы персистентности.

Как бы вы поделились тем, что у вас есть только один EntityManagerFactory для единицы персистентности?

Обычно разработчики создают вспомогательный класс с одноплодной EntityManagerFactory, такими как

public class EntityManagerFactoryHelper { 

    private static EntityManagerFactory factory; 

    static { 
     try { 
      // Set up factory right here 
     } catch(ExceptionInInitializerError e) { 
      throw e; 
     } 
    } 

    public static EntityManagerFactory getFactory() { 
     return this.factory; 
    } 

} 

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

Если вы хотите знать, почему я использую ErrorInInitializerError, его API ясно

Сигналы, неожиданное исключение произошло в статического инициализатора

...

Является ли это хорошим способом инициализации менеджера объектов?

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

public static br.com.helper.EntityManagerFactoryHelper.getFactory; 

public EmployeeService { 

    public void doSomething() { 
     EntityManager eManager = getFactory().createEntityManager(); 
     eManager.getTransaction().begin(); 

     EmployeeRepository repository = new EmployeeRepository(eManager); 

     eManager.getTransaction().commit(); 
    } 

} 

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

public void forEachUseCase() { 
     // Create an EntityManager 
     // Begin a Transaction 

     EmployeeRepository repository = new EmployeeRepository(eManager); 

     // And finally, commit 
    } 

Вы можете положиться на Spring, чтобы помочь вам избавиться от этого шаблонного кода.

+0

Я немного опаздываю на это, но знаете ли вы, что если вы используете стойкость, управляемую контейнером, и вы просматриваете блок персистентности своим именем JNDI, указанным в : (т.е. EntityManager manager = (EntityManager) context.lookup (jndiName);), состоит в том, что EM возвращал фактически новый EM каждый раз? Это EMF за сценой, выкачивающей EMs, или это просто глобальная EM, связанная с одним потоком? – djb

0

Брайан,

Это нормально делиться EntityManagerFactory, но это не так хорошо, чтобы поделиться EntityManager. См. Java Persistence wikibook.

Более современный подход состоял бы в том, чтобы делать одиночные списки с перечислениями. Таким образом, предполагается, что вы не ожидаете, чтобы обойти изменив имена сохраняемости единицы (я бы ожидать, что не произойдет, так или иначе) ...

Так идеально ...

  1. Использование синглтона для EntityManagerFactory экземпляр, на единицу персистентности.
  2. Создайте новый диспетчер сущностей для каждого вызова, чтобы его получить, и не делите их.

Используя перечисление для одноточечного механизма обеспечивает ... (Effective Java Second edition)

  1. сжатость
  2. Обеспечивает сериализацию оборудования для свободного
  3. предотвращает многократное инстанцирование EntityManagerFactory без проблем синхронизации. Это происходит из-за того, что конструкторы перечислений вызываются во время загрузки класса и не могут быть вызваны вашим кодом.
  4. Обеспечивает, что EntityManager не будет использоваться, если программист не сделает неправильный выбор.
public enum PersistenceUnitFactory 
{ 
    PERSISTENCE_UNIT_1("persistenceUnit1"), 
    PERSISTENCE_UNIT_2("persistenceUnit2"); 

    private final EntityManagerFactory emf; 
    /** 
    * Maps the persistence unit name to this instance of the enum. 
    * 
    * @param persistenceUnitName the name of the peristence unit in 
    *       persistence.xml 
    * 
    * @see #getPersistenceUnitName() 
    */ 
    PersistenceUnitFactory(final String persistenceUnitName) 
    { 
     emf = Persistence.createEntityManagerFactory(persistenceUnitName); 
    } 

    /** 
    * Creates a new {@link EntityManager}. NEVER share this across threads. 
    * 
    * @return a new {@link EntityManager} 
    */ 
    EntityManager createEntityManager() 
    { 
     return emf.createEntityManager(); 
    } 
} 

Тогда это так просто, как просить для EntityManager ...

PersistenceUnitFactory.PERSISTENCE_UNIT_1.createEntityManager(); 

Вы можете добавить больше сохраняемости единиц по мере необходимости.

Смежные вопросы