Hibernate SessionFactory contre JPA EntityManagerFactory

251

Je suis nouveau sur Hibernate et je ne sais pas s'il faut utiliser un Hibernate SessionFactoryou un JPA EntityManagerFactorypour créer un Hibernate Session.

Quelle est la différence entre ces deux? Quels sont les avantages et les inconvénients de l'utilisation de chacun d'entre eux?

elpisu
la source
6
Cette réponse à une question en double est vraiment bonne. stackoverflow.com/questions/23445830/…
Sanghyun Lee

Réponses:

365

Préférez EntityManagerFactoryet EntityManager. Ils sont définis par la norme JPA.

SessionFactoryet Sessionsont spécifiques à l'hibernation. Le EntityManagerinvoque la session d'hibernation sous le capot. Et si vous avez besoin de fonctionnalités spécifiques qui ne sont pas disponibles dans le EntityManager, vous pouvez obtenir la session en appelant:

Session session = entityManager.unwrap(Session.class);
Bozho
la source
2
@elpisu - Je ne peux pas recommander, en fait. J'ai utilisé uniquement la documentation officielle comme ressource d'apprentissage (au moins au cours des 2 dernières années), donc je ne sais rien d'autre de fiable. Mais les documents sont assez bons.
Bozho
7
@Bozho Je sais qu'il est tard mais quels sont les inconvénients de l'utilisation de SessionFactory et Session? Pourquoi l'utilisation de JPA est préférée? Merci
Mickael Marrache
12
@MickaelMarrache, l'utilisation de JPA est préférable à l'API Hibernate, car il s'agit d'une norme Java Enterprise. L'utilisation de JPA (et vous y limiter, sans utiliser les fonctionnalités spécifiques à Hibernate) améliore la portabilité de l'application, c'est-à-dire que vous avez la possibilité de basculer vers un cadre de persistance différent avec des modifications minimes de votre application, tant que ce cadre est également conforme à la norme JPA .
László van den Hoek,
2
Est-ce mieux simplement parce que c'est une norme d'entreprise? Je doute que. Les normes sont généralement lentes à évoluer et compliquées. Qu'en est-il de certains avantages réels? JPA est meilleur car il a TypedQuery, vous empêche de transtyper partout.
Bastian Voigt
1
Cette approche est d'obtenir Sessionde EntityManager, même que SessionFactory.getCurrentSession()? Je veux dire, ouvrira-t-il de nouveau Sessions'il n'est pas déjà créé? Comment ça marche dans un environnement multithread?
Sarvesh
32

Je veux ajouter à cela que vous pouvez également obtenir la session d'Hibernate en appelant la getDelegate()méthode à partir de EntityManager.

ex:

Session session = (Session) entityManager.getDelegate();
jouet
la source
28
On notera que unwrap()est à préférer au cours d' getDelegate()après les documents java: javaee 6 , et javaee 7 .
ryenus
22

Je préfère l' EntityManagerAPI JPA2 SessionFactory, car elle semble plus moderne. Un exemple simple:

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

Je pense qu'il est clair que le premier semble plus propre et qu'il est également plus facile à tester car EntityManager peut être facilement moqué.

Bastian Voigt
la source
30
Vous pouvez rendre n'importe quel code compliqué si vous le souhaitez. return sessionFactory.getCurrentSession().createQuery("from User where id=1").list()
2015 à 15h09
Comment directement vous avez obtenu entityManager et vous montrez que vous devez utiliser sessionfactory pour récupérer la session ..: D
JavaLearner
21

L'utilisation de l'approche EntityManagerFactory nous permet d'utiliser des annotations de méthode de rappel comme @PrePersist, @ PostPersist, @ PreUpdate sans configuration supplémentaire.

L'utilisation de rappels similaires lors de l'utilisation de SessionFactory nécessitera des efforts supplémentaires.

Les documents Hibernate associés peuvent être trouvés ici et ici .

Questions SOF connexes et discussion du forum de printemps

Kumar Sambhav
la source
21

SessionFactory contre. EntityManagerFactory

Comme je l'ai expliqué dans le Guide de l'utilisateur d'Hibernate , l'Hibernate SessionFactoryétend le JPA EntityManagerFactory, comme illustré par le diagramme suivant:

Relations JPA et Hibernate

Donc, SessionFactoryc'est aussi un JPA EntityManagerFactory.

Le SessionFactoryet le EntityManagerFactorycontiennent les métadonnées de mappage d'entité et vous permettent de créer un Hibernate Sessionou un EntityManager.

Session contre. EntityManager

Tout comme le SessionFactoryet EntityManagerFactory, l'Hibernate Sessionétend le JPA EntityManager. Ainsi, toutes les méthodes définies par le EntityManagersont disponibles dans Hibernate Session.

Le Sessionet le `EntityManager traduisent les transitions d'état d'entité en instructions SQL, comme SELECT, INSERT, UPDATE et DELETE.

Hibernate vs bootstrap JPA

Lors du démarrage d'une application JPA ou Hibernate, vous avez deux choix:

  1. Vous pouvez démarrer via le mécanisme natif Hibernate et créer un SessionFactoryvia le BootstrapServiceRegistryBuilder. Si vous utilisez Spring, le bootstrap Hibernate se fait via le LocalSessionFactoryBean, comme illustré par cet exemple GitHub .
  2. Ou, vous pouvez créer un JPA EntityManagerFactoryvia lePersistence classe ou le EntityManagerFactoryBuilder. Si vous utilisez Spring, le bootstrap JPA se fait via le LocalContainerEntityManagerFactoryBean, comme illustré par cet exemple GitHub .

L'amorçage via JPA est à privilégier. En effet, le JPA FlushModeType.AUTOest un bien meilleur choix que l'héritage FlushMode.AUTO, ce qui rompt la cohérence de lecture-écriture pour les requêtes SQL natives .

Développer WPA pour mettre en veille prolongée

De plus, si vous démarrez via JPA et que vous avez injecté le EntityManagerFactory via l' @PersistenceUnitannotation:

@PersistenceUnit
private EntityManagerFactory entityManagerFactory;

Vous pouvez facilement accéder au sous-jacent Sessionfactory utilisant la unwrapméthode:

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

La même chose peut être faite avec l'APP EntityManager. Si vous injectez leEntityManager via l' @PersistenceContextannotation:

@PersistenceContext
private EntityManager entityManager;

Vous pouvez facilement accéder au sous-jacent Session utilisant la unwrapméthode:

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

Conclusion

Par conséquent, vous devez démarrer via JPA, utiliser les symboles EntityManagerFactoryet EntityManageret les décompresser uniquement vers leurs interfaces Hibernate associées lorsque vous souhaitez accéder à certaines méthodes spécifiques à Hibernate qui ne sont pas disponibles dans JPA, comme extraire l'entité via son identifiant naturel .

Vlad Mihalcea
la source
2

En utilisant EntityManager, le code n'est plus étroitement associé à la mise en veille prolongée. Mais pour cela, en utilisation, nous devons utiliser:

javax.persistence.EntityManager

au lieu de

org.hibernate.ejb.HibernateEntityManager

De même, pour EntityManagerFactory, utilisez l'interface javax. De cette façon, le code est faiblement couplé. S'il existe une meilleure implémentation de JPA 2 que l'hibernation, la commutation serait facile. Dans le cas extrême, nous pourrions taper cast à HibernateEntityManager.

Sairam Krish
la source
2

EntityManagerFactory est l'implémentation standard, elle est la même dans toutes les implémentations. Si vous migrez votre ORM pour un autre fournisseur comme EclipseLink, il n'y aura aucun changement dans l'approche de gestion de la transaction. En revanche, si vous utilisez la fabrique de sessions hibernate, elle est liée aux API hibernate et ne peut pas migrer vers un nouveau fournisseur.

DEMEURE
la source
1

L'interface EntityManager est similaire à sessionFactory en veille prolongée. EntityManager sous le package javax.persistance mais session et sessionFactory sous le package org.hibernate.Session / sessionFactory.

Le gestionnaire d'entités est spécifique à JPA et la session / sessionFactory est spécifique à l'hibernation.

Avvappa Hegadyal
la source
Votre réponse est correcte, mais est essentiellement la même que celle à laquelle Sangyun Lee fait référence dans ses commentaires ... donc un doublon.
RWC