Hibernacja SessionFactory vs. JPA EntityManagerFactory


251

Jestem nowy w Hibernacji i nie jestem pewien, czy użyć Hibernacji, SessionFactoryczy JPA, EntityManagerFactoryaby utworzyć Hibernację Session.

Jaka jest różnica między tymi dwoma? Jakie są zalety i wady korzystania z każdego z nich?


6
Ta odpowiedź na zduplikowane pytanie jest naprawdę dobra. stackoverflow.com/questions/23445830/…
Sanghyun Lee

Odpowiedzi:


365

Wolę EntityManagerFactoryi EntityManager. Są one zdefiniowane w standardzie JPA.

SessionFactoryi Sessionsą specyficzne dla hibernacji. EntityManagerWywołuje sesji hibernacji pod maską. A jeśli potrzebujesz określonych funkcji, które nie są dostępne w EntityManager, możesz uzyskać sesję, dzwoniąc:

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

2
@elpisu - właściwie nie mogę polecić. Używam tylko oficjalnej dokumentacji jako źródła wiedzy (przynajmniej w ciągu ostatnich 2 lat), więc nie wiem nic innego. Ale dokumenty są wystarczająco dobre.
Bozho

7
@Bozho Wiem, że jest późno, ale jakie są wady korzystania z SessionFactory i Session? Dlaczego preferowane jest stosowanie JPA? Dzięki
Mickael Marrache, 11.11.11

12
@MickaelMarrache użycie JPA powinno być preferowane w stosunku do Hibernate API, ponieważ jest to standard Java Enterprise. Korzystanie z JPA (i ograniczanie się do niego, bez korzystania z funkcji specyficznych dla hibernacji) poprawia przenośność aplikacji, tzn. Masz możliwość przełączenia się na inną platformę trwałości z minimalnymi zmianami w aplikacji, o ile ta platforma jest również zgodna ze standardem JPA .
László van den Hoek

2
Czy jest lepiej tylko dlatego, że jest to standard korporacyjny? Wątpię w to. Normy są zwykle powolne i ewoluują i są skomplikowane. Co z niektórymi korzyściami z życia? JPA jest lepszy, ponieważ ma TypedQuery, powstrzymuje cię przed rzutowaniem czcionek w dowolnym miejscu.
Bastian Voigt,

1
Jest to podejście, aby uzyskać Sessionod EntityManager, tak samo jak SessionFactory.getCurrentSession()? Mam na myśli, czy otworzy się nowy, Sessionjeśli jeszcze nie został utworzony? Jak to działa w środowisku wielowątkowym?
Sarvesh

32

Chcę dodać, że możesz także uzyskać sesję Hibernacji, wywołując getDelegate()metodę z EntityManager.

dawny:

Session session = (Session) entityManager.getDelegate();

28
Należy zauważyć, że unwrap()to preferowane przez getDelegate()według Dokumenty JAVA: JavaEE 6 i JavaEE 7 .
ryenus

22

Wolę EntityManagerAPI JPA2 niż SessionFactory, ponieważ wydaje się bardziej nowoczesny. Jeden prosty przykład:

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;
}

Myślę, że jasne jest, że pierwszy wygląda na czystszy i łatwiej go przetestować, ponieważ EntityManager można łatwo wyśmiewać.


30
Jeśli chcesz, możesz skomplikować dowolny kod. return sessionFactory.getCurrentSession().createQuery("from User where id=1").list()
wst

Jak bezpośrednio uzyskałeś entityManager i pokazujesz, że musisz użyć sessionfactory, aby pobrać sesję ..: D
JavaLearner 25.04.2018

21

Korzystanie z podejścia EntityManagerFactory pozwala nam korzystać z adnotacji metod wywołania zwrotnego, takich jak @PrePersist, @ PostPersist, @ PreUpdate bez dodatkowej konfiguracji.

Korzystanie z podobnych wywołań zwrotnych podczas korzystania z SessionFactory będzie wymagać dodatkowych wysiłków.

Powiązane dokumenty Hibernacja można znaleźć tutaj i tutaj .

Powiązane pytanie SOF i dyskusja na forum wiosennym


21

SessionFactory vs. EntityManagerFactory

Jak wyjaśniłem w Przewodniku użytkownika Hibernacji , Hibernacja SessionFactoryrozszerza JPA EntityManagerFactory, co ilustruje poniższy schemat:

Związek JPA i Hibernacja

Tak, SessionFactoryto również JPA EntityManagerFactory.

Zarówno SessionFactoryi EntityManagerFactoryzawierają metadane odwzorowania encji i umożliwiają utworzenie hibernacji Sessionlub a EntityManager.

Session vs. EntityManager

Podobnie jak SessionFactoryi EntityManagerFactoryHibernacja Sessionrozszerza JPA EntityManager. Tak więc wszystkie metody zdefiniowane przez EntityManagersą dostępne w Hibernacji Session.

A Sessionoraz `EntityManager tłumaczą przejścia stanu encji na instrukcje SQL, takie jak SELECT, INSERT, UPDATE i DELETE.

Hibernacja kontra bootstrap JPA

Podczas ładowania aplikacji JPA lub Hibernacji masz dwie możliwości:

  1. Możesz uruchomić system za pomocą natywnego mechanizmu Hibernacja i utworzyć za SessionFactorypomocą BootstrapServiceRegistryBuilder. Jeśli używasz Springa, Hibernacja bootstrap odbywa się za pomocą LocalSessionFactoryBean, jak pokazano w tym przykładzie GitHub .
  2. Lub możesz utworzyć JPA EntityManagerFactoryza pośrednictwem Persistenceklasy lub EntityManagerFactoryBuilder. Jeśli używasz Springa, bootstrap JPA odbywa się za pomocą LocalContainerEntityManagerFactoryBean, jak pokazano w tym przykładzie GitHub .

Preferowane jest ładowanie poprzez JPA. Jest tak, ponieważ JPA FlushModeType.AUTOjest znacznie lepszym wyborem niż starsza wersja FlushMode.AUTO, która łamie spójność odczytu i zapisu w rodzimych zapytaniach SQL .

Rozpakowywanie JPA do Hibernacji

Ponadto, jeśli bootstrap przez WZP, a ty wstrzyknął EntityManagerFactorypośrednictwem @PersistenceUnitadnotacji:

@PersistenceUnit
private EntityManagerFactory entityManagerFactory;

Możesz łatwo uzyskać dostęp do instrumentu bazowego Sessionfactoryza pomocą unwrapmetody:

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

To samo można zrobić z WZP EntityManager. Jeśli wstrzyknąć EntityManagerza pomocą @PersistenceContextadnotacji:

@PersistenceContext
private EntityManager entityManager;

Możesz łatwo uzyskać dostęp do instrumentu bazowego Sessionza pomocą unwrapmetody:

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

Wniosek

Tak więc powinieneś bootować pasek za pomocą JPA, używać EntityManagerFactoryi EntityManager, i rozpakowywać je do powiązanych interfejsów Hibernacja tylko wtedy, gdy chcesz uzyskać dostęp do niektórych specyficznych metod Hibernacji, które nie są dostępne w JPA, takich jak pobieranie encji za pomocą jej naturalnego identyfikatora .


2

Korzystając z EntityManager, kod nie jest już ściśle powiązany z hibernacją. Ale w tym celu w użyciu powinniśmy użyć:

javax.persistence.EntityManager

zamiast

org.hibernate.ejb.HibernateEntityManager

Podobnie dla EntityManagerFactory użyj interfejsu javax. W ten sposób kod jest luźno powiązany. Jeśli istnieje lepsza implementacja JPA 2 niż hibernacja, przełączanie byłoby łatwe. W skrajnym przypadku możemy wpisać cast do HibernateEntityManager.


2

EntityManagerFactory to standardowa implementacja, jest taka sama we wszystkich implementacjach. W przypadku migracji ORM dla dowolnego innego dostawcy, takiego jak EclipseLink, nie będzie żadnych zmian w podejściu do obsługi transakcji. Natomiast w przypadku korzystania z fabryki sesji hibernacji jest ona powiązana z interfejsami API hibernacji i nie można przeprowadzić migracji do nowego dostawcy.


1

Interfejs EntityManager jest podobny do sessionFactory w trybie hibernacji. EntityManager w pakiecie javax.persistance, ale session & sessionFactory w org.hibernate.Session / sessionFactory.

Menedżer jednostek jest specyficzny dla JPA, a sesja / sesja jest specyficzna dla hibernacji.


Twoja odpowiedź jest poprawna, ale zasadniczo jest taka sama jak odpowiedź, do której Sangyun Lee odnosi się w swoich komentarzach ... więc jest duplikatem.
RWC
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.