Многоразовый Hibernate EntityManager (J2SE) - PullRequest
4 голосов
/ 13 сентября 2009

мы разрабатываем приложение J2SE и используем Hibernate для нашего уровня персистентности. Для доступа к нашей базе данных я создал одноэлементный класс, который имеет все необходимые методы для получения и сохранения объектов из базы данных. Но как только я создал второй способ получения объектов, я сразу понял, что у меня вонючий код:

public enum DataManager {
  Instance;

  public List<Employee> getEmployees() {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
    EntityManager em = emf.createEntityManager();
    EntityTransaction tx = em.getTransaction();
    tx.begin();
    List<?> ems = em.createQuery("select e from Employee e").getResultList();
    List<Employee> result = new ArrayList<Employee>();
    for (Object o : ems )
      result.add((Employee) o);

    tx.commit();
    em.close();
    emf.close();
    return result;
  }

  public List<Shift> getShifts() {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
    EntityManager em = emf.createEntityManager();
    EntityTransaction tx = em.getTransaction();
    tx.begin();
    List<?> ems = em.createQuery("select s from Shift s").getResultList();
    List<Shift> result = new ArrayList<Shift>();
    for (Object o : ems )
      result.add((Shift) o);

    tx.commit();
    em.close();
    emf.close();

    return result;
  }
}

Так что мне определенно нужно переделать это. Документация Hibernate имеет класс HibernateUtility для обработки сеансов и транзакций. Но я использую EntityManager.

Буквально вчера я обнаружил эту очень интересную статью под названием Общий шаблон DAO с JDK 5.0 . Он написан в 2005 году, поэтому я действительно не уверен, что он все еще действителен. Он снова использует сеансы.

Это то, что вы используете? Если нет, есть лучшее решение?

Спасибо.

Примечание 1: я довольно новичок в Hibernate
Примечание 2: название не выглядит правильным

Ответы [ 4 ]

3 голосов
/ 13 сентября 2009

Я настоятельно рекомендую вам использовать Spring для конфигурирования и управления вашего синглтона EntityManager. Нет больше запахов. Такая проблема - это раздражающая механика, о которой действительно не нужно беспокоиться.

1 голос
/ 14 сентября 2009

Если ваш контейнер поддерживает EJB или вы используете spring, вы можете запросить EntityManagerFactory.

@PersistenceUnit private EntityManagerFactory emf;

Другой вариант - использовать Spring или любой другой IoC для инъекции EntityManagerFactory или EntityManager (с правильной областью видимости).

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

Взгляните на ссылку ниже, она предоставляет хорошую информацию по этому вопросу. https://blueprints.dev.java.net/bpcatalog/ee5/persistence/webonlyapp.html

ИМХО, лучший способ - использовать IoC, чтобы позаботиться о внедрении EntityManager и / или EntityManagerFactory.

0 голосов
/ 13 сентября 2009

Простой рефакторинг будет состоять в том, чтобы извлечь общий код в один служебный метод:

public List<Employee> getEmployees() {
    return getObjects("Employee", Employee.class);
}

private <T> List<T> getObjects(String typeName, Class<T> typeClass) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
    EntityManager em = emf.createEntityManager();
    EntityTransaction tx = em.getTransaction();
    tx.begin();
    List<?> ems = em.createQuery("select o from " + typeName + " o").getResultList();
    List<T> result = new ArrayList<T>();
    for (Object o: ems)
      result.add(typeClass.cast(o));
    tx.commit();
    em.close();
    emf.close();
    return result;
  }

Будет ли это против запаха, который беспокоит вас? Или есть еще?

0 голосов
/ 13 сентября 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...