Hibernate SessionFactory против JPA EntityManagerFactory

251

Я новичок в Hibernate, и я не уверен, использовать ли Hibernate SessionFactoryили JPA EntityManagerFactoryдля создания Hibernate Session.

В чем разница между этими двумя? Каковы плюсы и минусы использования каждого из них?

elpisu
источник
6
Этот ответ на дублированный вопрос действительно хорош. stackoverflow.com/questions/23445830/…
Санхьюн Ли

Ответы:

365

Предпочитаю EntityManagerFactoryи EntityManager. Они определены стандартом JPA.

SessionFactoryи Sessionспецифичны для спящего режима. EntityManagerВызывает сеанс спящего режима под капотом. И если вам нужны некоторые специфические функции, которые не доступны в EntityManager, вы можете получить сеанс, позвонив:

Session session = entityManager.unwrap(Session.class);
Bozho
источник
2
@elpisu - я не могу рекомендовать, на самом деле. Я использовал только официальную документацию в качестве учебного ресурса (по крайней мере, в последние 2 года), поэтому я не знаю ничего более надежного. Но документы достаточно хороши.
Божо
7
@ Божо Я знаю, что уже поздно, но каковы недостатки использования SessionFactory и Session? Почему использование JPA является предпочтительным? Спасибо
Mickael Marrache
12
@MickaelMarrache использование JPA предпочтительнее, чем Hibernate API, потому что это стандарт Java Enterprise. Использование JPA (и ограничение на него без использования специфичных для Hibernate функций) улучшает переносимость приложения, т. Е. У вас есть возможность переключиться на другую постоянную среду с минимальными изменениями в приложении, если эта среда также соответствует стандарту JPA ,
Ласло ван ден Хук
2
Это лучше только потому, что это стандарт предприятия? Сомневаюсь. Стандарты, как правило, медленно развиваются и усложняются. Как насчет реальных преимуществ? JPA лучше, потому что он имеет TypedQuery, останавливает вас от повсеместной типизации.
Бастиан Фойгт
1
Является ли этот подход , чтобы получить Sessionот EntityManager, так же как SessionFactory.getCurrentSession()? Я имею в виду, откроется Sessionли оно новым, если оно еще не создано? Как это работает в многопоточной среде?
Сарвеш
32

Я хочу добавить к этому, что вы также можете получить сессию Hibernate, вызвав getDelegate()метод из EntityManager.

например:

Session session = (Session) entityManager.getDelegate();
toytoy
источник
28
обратите внимание, что unwrap()это должно быть предпочтительнее, чем в getDelegate()соответствии с документами Java: Java 6 и Java 7 .
Ryenus
22

Я предпочитаю JPA2 EntityManager API SessionFactory, потому что он более современный. Один простой пример:

JPA:

@PersistenceContext
EntityManager entityManager;

public List<MyEntity> findSomeApples() {
  return entityManager
     .createQuery("from MyEntity where apples=7", MyEntity.class)
     .getResultList();
}

SessionFactory:

@Autowired
SessionFactory sessionFactory;

public List<MyEntity> findSomeApples() {
  Session session = sessionFactory.getCurrentSession();
  List<?> result = session.createQuery("from MyEntity where apples=7")
      .list();
  @SuppressWarnings("unchecked")
  List<MyEntity> resultCasted = (List<MyEntity>) result;
  return resultCasted;
}

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

Бастиан Фойгт
источник
30
Вы можете сделать любой код сложным, если хотите. return sessionFactory.getCurrentSession().createQuery("from User where id=1").list()
WST
Как непосредственно у вас есть entityManager, и вы показываете, что должны использовать sessionfactory для получения сессии ..: D
JavaLearner
21

Использование подхода EntityManagerFactory позволяет нам использовать аннотации методов обратного вызова, такие как @PrePersist, @ PostPersist, @ PreUpdate без дополнительной настройки.

Использование подобных обратных вызовов при использовании SessionFactory потребует дополнительных усилий.

Связанные документы Hibernate можно найти здесь и здесь .

Связанные вопросы SOF и весенний форум

Кумар Самбхав
источник
21

SessionFactory против EntityManagerFactory

Как я объяснил в Руководстве пользователя Hibernate , Hibernate SessionFactoryрасширяет JPA EntityManagerFactory, как показано на следующей диаграмме:

JPA и Hibernate отношения

Таким образом, SessionFactoryэто также JPA EntityManagerFactory.

Оба SessionFactoryи EntityManagerFactoryсодержат метаданные отображения сущностей и позволяют вам создавать Hibernate Sessionили a EntityManager.

Session против EntityManager

Так же как SessionFactoryи EntityManagerFactory, Hibernate Sessionрасширяет JPA EntityManager. Итак, все методы, определенные в EntityManager, доступны в HibernateSession .

SessionИ `EntityManager переводить переходы между состояниями сущностей в операторы SQL, как SELECT, INSERT, UPDATE и DELETE.

Hibernate против JPA начальной загрузки

При начальной загрузке приложения JPA или Hibernate у вас есть два варианта:

  1. Вы можете загрузиться с помощью встроенного механизма Hibernate и создать a с SessionFactoryпомощью BootstrapServiceRegistryBuilder. Если вы используете Spring, начальная загрузка Hibernate выполняется через LocalSessionFactoryBean, как показано в этом примере GitHub .
  2. Или вы можете создать JPA EntityManagerFactoryчерез Persistenceкласс или EntityManagerFactoryBuilder. Если вы используете Spring, начальная загрузка JPA выполняется через LocalContainerEntityManagerFactoryBean, как показано в этом примере GitHub .

Начальная загрузка через JPA должна быть предпочтительной. Это потому, что JPA FlushModeType.AUTOявляется гораздо лучшим выбором, чем унаследованная версия FlushMode.AUTO, которая нарушает согласованность операций чтения и записи для собственных запросов SQL .

Развертывание JPA в Hibernate

Кроме того, если вы загружаете через JPA, и вы добавили аннотацию EntityManagerFactoryчерез @PersistenceUnit:

@PersistenceUnit
private EntityManagerFactory entityManagerFactory;

Вы можете легко получить доступ к базовому, Sessionfactoryиспользуя unwrapметод:

SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);

То же самое можно сделать с JPA EntityManager. Если вы вводите EntityManagerчерез @PersistenceContextаннотацию:

@PersistenceContext
private EntityManager entityManager;

Вы можете легко получить доступ к базовому, Sessionиспользуя unwrapметод:

Session session = entityManager.unwrap(Session.class);

Вывод

Таким образом, вы должны загружать через JPA, использовать EntityManagerFactoryи EntityManagerи развертывать их только в связанных с ними интерфейсах Hibernate, когда вы хотите получить доступ к некоторым специфичным для Hibernate методам, которые недоступны в JPA, например, к извлечению объекта через его естественный идентификатор .

Влад Михалча
источник
2

Используя EntityManager, код больше не тесно связан с Hibernate. Но для этого в использовании мы должны использовать:

javax.persistence.EntityManager

вместо того

org.hibernate.ejb.HibernateEntityManager

Аналогично, для EntityManagerFactory используйте интерфейс javax. Таким образом, код слабо связан. Если реализация JPA 2 лучше, чем в спящем режиме, переключение будет простым. В крайнем случае мы можем ввести приведение к HibernateEntityManager.

Сайрам Криш
источник
2

EntityManagerFactory является стандартной реализацией, она одинакова для всех реализаций. Если вы перенесете ORM на любого другого провайдера, такого как EclipseLink, подход к обработке транзакции не изменится. Напротив, если вы используете фабрику сессий hibernate, она привязана к API hibernate и не может перейти на нового поставщика.

ОБИТЕЛЬ
источник
1

Интерфейс EntityManager похож на sessionFactory в спящем режиме. EntityManager в пакете javax.persistance, но session и sessionFactory в пакете org.hibernate.Session / sessionFactory.

Менеджер сущностей специфичен для JPA, а session / sessionFactory - для режима гибернации.

Авваппа Хегадял
источник
Ваш ответ правильный, но по сути такой же, как ответ, который Сангюн Ли упоминает в своих комментариях ... так что дубликат.
RWC