Hibernate SessionFactory vs. JPA EntityManagerFactory


251

Sono nuovo di Hibernate e non sono sicuro se utilizzare un Hibernate SessionFactoryo un JPA EntityManagerFactoryper creare un Hibernate Session.

Qual è la differenza tra questi due? Quali sono i pro e i contro dell'utilizzo di ognuno di questi?


6
Questa risposta a una domanda duplicata è davvero buona. stackoverflow.com/questions/23445830/...
Sanghyun Lee

Risposte:


365

Preferire EntityManagerFactorye EntityManager. Sono definiti dallo standard JPA.

SessionFactorye Sessionsono specifici dell'ibernazione. La EntityManagerinvoca la sessione di ibernazione sotto il cofano. E se hai bisogno di alcune funzionalità specifiche che non sono disponibili in EntityManager, puoi ottenere la sessione chiamando:

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

2
@elpisu - In realtà non posso raccomandarlo. Ho usato solo la documentazione ufficiale come risorsa di apprendimento (almeno negli ultimi 2 anni), quindi non conosco nient'altro di affidabile. Ma i documenti sono abbastanza buoni.
Bozho,

7
@Bozho So che è tardi, ma quali sono gli svantaggi dell'utilizzo di SessionFactory e Session? Perché è preferito l'uso di JPA? Grazie
Mickael Marrache l'

12
@MickaelMarrache l'uso dell'APP deve essere preferito rispetto all'API Hibernate, poiché è uno standard Java Enterprise. L'uso di JPA (e limitarsi ad esso, senza utilizzare le funzionalità specifiche di Hibernate) migliora la portabilità dell'applicazione, ovvero è possibile passare a un diverso framework di persistenza con modifiche minime all'applicazione, purché tale framework sia conforme allo standard JPA .
László van den Hoek,

2
È meglio solo perché è uno standard aziendale? Ne dubito. Gli standard sono generalmente lenti a evolversi e complicati. Che dire di alcuni benefici della vita reale? JPA è migliore perché ha TypedQuery, ti impedisce di scrivere a macchina dappertutto.
Bastian Voigt

1
È questo approccio per ottenere Sessionda EntityManager, stessa SessionFactory.getCurrentSession()? Voglio dire, si aprirà nuovo Sessionse non è già stato creato? Come funziona in ambiente multithread?
Sarvesh,

32

Voglio aggiungere a questo che puoi anche ottenere la sessione di Hibernate chiamando il getDelegate()metodo da EntityManager.

ex:

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

28
si noti che unwrap()è preferibile rispetto getDelegate()ai documenti java: javaee 6 e javaee 7 .
reno

22

Preferisco l' EntityManagerAPI JPA2 rispetto a SessionFactory, perché sembra più moderno. Un semplice esempio:

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

Penso che sia chiaro che il primo sembra più pulito ed è anche più facile da testare perché EntityManager può essere facilmente deriso.


30
Puoi complicare qualsiasi codice se vuoi. return sessionFactory.getCurrentSession().createQuery("from User where id=1").list()
wst

Quanto direttamente hai entityManager e stai mostrando che devi usare sessionfactory per recuperare la sessione ..: D
JavaLearner


21

SessionFactory vs. EntityManagerFactory

Come ho spiegato nella Guida dell'utente di Hibernate , Hibernate SessionFactoryestende l'APP EntityManagerFactory, come illustrato dal diagramma seguente:

Relazione JPA e Hibernate

Quindi, SessionFactoryè anche un JPA EntityManagerFactory.

Sia il SessionFactoryche il EntityManagerFactorycontengono i metadati di mappatura dell'entità e consentono di creare un ibernazione Sessiono un EntityManager.

Session vs. EntityManager

Proprio come il SessionFactorye EntityManagerFactory, l'ibernato Sessionestende l'APP EntityManager. Quindi, tutti i metodi definiti da EntityManagersono disponibili in Hibernate Session.

Il Sessione il `EntityManager traducono le transizioni dello stato dell'entità in istruzioni SQL, come SELECT, INSERT, UPDATE e DELETE.

Bootstrap Hibernate vs. JPA

Quando si avvia il bootstrap di un'applicazione JPA o Hibernate, sono disponibili due opzioni:

  1. È possibile eseguire il bootstrap tramite il meccanismo nativo di Hibernate e creare un SessionFactorytramite BootstrapServiceRegistryBuilder. Se stai usando Spring, il bootstrap di Hibernate viene eseguito tramite LocalSessionFactoryBean, come illustrato da questo esempio GitHub .
  2. In alternativa, è possibile creare un JPA EntityManagerFactorytramite la Persistenceclasse o il EntityManagerFactoryBuilder. Se stai usando Spring, il bootstrap JPA viene eseguito tramite LocalContainerEntityManagerFactoryBean, come illustrato da questo esempio GitHub .

Il bootstrap tramite JPA deve essere preferito. Questo perché JPA FlushModeType.AUTOè una scelta molto migliore rispetto all'eredità FlushMode.AUTO, che interrompe la coerenza di lettura e scrittura per le query SQL native .

Non imballare JPA in ibernazione

Inoltre, se si avvia bootstrap tramite JPA e si è iniettato EntityManagerFactorytramite l' @PersistenceUnitannotazione:

@PersistenceUnit
private EntityManagerFactory entityManagerFactory;

Puoi facilmente accedere al sottostante Sessionfactoryusando il unwrapmetodo:

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

Lo stesso può essere fatto con l'APP EntityManager. Se si inietta EntityManagertramite l' @PersistenceContextannotazione:

@PersistenceContext
private EntityManager entityManager;

Puoi facilmente accedere al sottostante Sessionusando il unwrapmetodo:

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

Conclusione

Pertanto, è necessario eseguire il bootstrap tramite JPA, utilizzare EntityManagerFactorye EntityManagere scartarli solo sulle interfacce Hibernate associate quando si desidera accedere ad alcuni metodi specifici di Hibernate non disponibili in JPA, come recuperare l'entità tramite il suo identificatore naturale .


2

Utilizzando EntityManager, il codice non è più strettamente accoppiato con l'ibernazione. Ma per questo, in uso dovremmo usare:

javax.persistence.EntityManager

invece di

org.hibernate.ejb.HibernateEntityManager

Allo stesso modo, per EntityManagerFactory, utilizzare l'interfaccia javax. In questo modo, il codice è liberamente accoppiato. Se esiste un'implementazione JPA 2 migliore di quella in letargo, la commutazione sarebbe facile. In casi estremi, potremmo digitare cast in HibernateEntityManager.


2

EntityManagerFactory è l'implementazione standard, è la stessa in tutte le implementazioni. Se esegui la migrazione del tuo ORM per qualsiasi altro provider come EclipseLink, non ci saranno cambiamenti nell'approccio alla gestione della transazione. Al contrario, se si utilizza la factory di sessione di hibernate, è legata alle API di ibernazione e non può migrare verso un nuovo fornitore.


1

L'interfaccia EntityManager è simile a sessionFactory in ibernazione. EntityManager nel pacchetto javax.persistance ma session e sessionFactory in org.hibernate.Session / sessionFactory pacchetto.

Il gestore entità è specifico per JPA e session / sessionFactory sono specifici di ibernazione.


La tua risposta è corretta, ma è essenzialmente la stessa della risposta a cui Sangyun Lee fa riferimento nei suoi commenti ... quindi un duplicato.
RWC,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.