Hibernate SessionFactory vs. JPA EntityManagerFactory

251

Ich bin neu im Ruhezustand und bin mir nicht sicher, ob ich einen Ruhezustand SessionFactoryoder eine JPA verwenden soll EntityManagerFactory, um einen Ruhezustand zu erstellen Session.

Was ist der Unterschied zwischen diesen beiden? Was sind die Vor- und Nachteile jeder dieser Anwendungen?

Elpisu
quelle
6
Diese Antwort auf eine doppelte Frage ist wirklich gut. stackoverflow.com/questions/23445830/…
Sanghyun Lee

Antworten:

365

Bevorzugen EntityManagerFactoryund EntityManager. Sie werden durch den JPA-Standard definiert.

SessionFactoryund Sessionsind hibernate-spezifisch. Der EntityManagerruft den Ruhezustand unter der Haube auf. Und wenn Sie einige spezifische Funktionen benötigen, die in der nicht verfügbar sind EntityManager, können Sie die Sitzung erhalten, indem Sie Folgendes aufrufen:

Session session = entityManager.unwrap(Session.class);
Bozho
quelle
2
@elpisu - kann ich eigentlich nicht empfehlen. Ich habe nur die offizielle Dokumentation als Lernressource verwendet (zumindest in den letzten 2 Jahren), daher weiß ich nichts Zuverlässiges. Aber die Dokumente sind gut genug.
Bozho
7
@Bozho Ich weiß, dass es spät ist, aber was sind die Nachteile der Verwendung von SessionFactory und Session? Warum wird die Verwendung von JPA bevorzugt? Vielen Dank
Mickael Marrache
12
@MickaelMarrache Die Verwendung von JPA ist der Hibernate-API vorzuziehen, da es sich um einen Java Enterprise-Standard handelt. Die Verwendung von JPA (und die Beschränkung auf JPA ohne Verwendung von Hibernate-spezifischen Funktionen) verbessert die Anwendungsportabilität, dh Sie haben die Möglichkeit, mit minimalen Änderungen an Ihrer Anwendung zu einem anderen Persistenz-Framework zu wechseln, sofern dieses Framework auch dem JPA-Standard entspricht .
László van den Hoek
2
Ist es besser, nur weil es ein Unternehmensstandard ist? Ich bezweifle das. Standards entwickeln sich normalerweise nur langsam und sind kompliziert. Was ist mit einigen Vorteilen aus dem wirklichen Leben? JPA ist besser, weil es TypedQuery hat und Sie davon abhält, überall Typografie zu schreiben.
Bastian Voigt
1
Ist dieser Ansatz zu bekommen Sessionaus EntityManager, genau wie SessionFactory.getCurrentSession()? Ich meine, wird es neu geöffnet, Sessionwenn es nicht bereits erstellt wurde? Wie funktioniert es in einer Multithread-Umgebung?
Sarvesh
32

Ich möchte hinzufügen, dass Sie die Sitzung von Hibernate auch erhalten können, indem Sie die getDelegate()Methode von aufrufen EntityManager.

Ex:

Session session = (Session) entityManager.getDelegate();
Spielzeug
quelle
28
Man beachte , dass unwrap()ist zu bevorzugen, mehr als getDelegate()nach der Java - Dokumentation: JavaEE 6 und JavaEE 7 .
Ryenus
22

Ich bevorzuge die JPA2- EntityManagerAPI SessionFactory, weil sie sich moderner anfühlt. Ein einfaches Beispiel:

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

Ich denke, es ist klar, dass der erste sauberer aussieht und auch einfacher zu testen ist, da EntityManager leicht verspottet werden kann.

Bastian Voigt
quelle
30
Sie können jeden Code komplizieren, wenn Sie möchten. return sessionFactory.getCurrentSession().createQuery("from User where id=1").list()
wst
Wie direkt Sie entityManager erhalten haben und Sie zeigen, dass Sie sessionfactory verwenden müssen, um die Sitzung abzurufen ..: D
JavaLearner
21

Mit dem EntityManagerFactory-Ansatz können wir Annotationen für Rückrufmethoden wie @PrePersist, @ PostPersist, @ PreUpdate ohne zusätzliche Konfiguration verwenden.

Die Verwendung ähnlicher Rückrufe während der Verwendung von SessionFactory erfordert zusätzliche Anstrengungen.

Verwandte Hibernate-Dokumente finden Sie hier und hier .

Verwandte SOF-Frage und Diskussion im Frühjahrsforum

Kumar Sambhav
quelle
21

SessionFactory vs. EntityManagerFactory

Wie ich im Hibernate-Benutzerhandbuch erläutert habe , erweitert der Hibernate SessionFactorydie JPA EntityManagerFactory, wie in der folgenden Abbildung dargestellt:

JPA und Ruhezustand Beziehung

Das SessionFactoryist also auch ein JPA EntityManagerFactory.

Sowohl die SessionFactoryals auch die EntityManagerFactoryenthalten die Entitätszuordnungsmetadaten und ermöglichen Ihnen das Erstellen eines Ruhezustands Sessionoder eines Ruhezustands EntityManager.

Session vs. EntityManager

Genau wie die SessionFactoryund EntityManagerFactorydie Hibernate Sessionerweitert die JPA EntityManager. Daher sind alle durch das definierten Methoden EntityManagerim Ruhezustand verfügbar Session.

Der Sessionund der EntityManager übersetzen Entitätsstatusübergänge in SQL-Anweisungen wie SELECT, INSERT, UPDATE und DELETE.

Ruhezustand vs. JPA-Bootstrap

Beim Bootstrapping einer JPA- oder Hibernate-Anwendung haben Sie zwei Möglichkeiten:

  1. Sie können über den nativen Hibernate-Mechanismus booten und SessionFactoryüber den BootstrapServiceRegistryBuilder. Wenn Sie Spring verwenden, erfolgt der Hibernate-Bootstrap über LocalSessionFactoryBean, wie in diesem GitHub-Beispiel dargestellt .
  2. Oder Sie können eine JPA EntityManagerFactoryüber die PersistenceKlasse oder die erstellen EntityManagerFactoryBuilder. Wenn Sie Spring verwenden, erfolgt der JPA-Bootstrap über LocalContainerEntityManagerFactoryBean, wie in diesem GitHub-Beispiel dargestellt .

Bootstrapping über JPA ist zu bevorzugen. Dies FlushModeType.AUTOliegt daran, dass der JPA eine viel bessere Wahl ist als das Legacy FlushMode.AUTO, wodurch die Konsistenz beim Lesen und Schreiben für native SQL-Abfragen beeinträchtigt wird .

JPA in den Ruhezustand auspacken

Wenn Sie über JPA booten und das EntityManagerFactoryüber die @PersistenceUnitAnnotation eingefügt haben:

@PersistenceUnit
private EntityManagerFactory entityManagerFactory;

SessionfactoryMit der folgenden unwrapMethode können Sie problemlos auf den Basiswert zugreifen :

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

Das gleiche kann mit der JPA gemacht werden EntityManager. Wenn Sie die EntityManagerüber die @PersistenceContextAnmerkung injizieren :

@PersistenceContext
private EntityManager entityManager;

SessionMit der folgenden unwrapMethode können Sie problemlos auf den Basiswert zugreifen :

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

Fazit

Sie sollten daher über JPA booten , das EntityManagerFactoryund verwenden EntityManagerund diese nur dann in die zugehörigen Hibernate-Schnittstellen auspacken, wenn Sie Zugriff auf einige Hibernate-spezifische Methoden erhalten möchten, die in JPA nicht verfügbar sind, z. B. das Abrufen der Entität über ihre natürliche Kennung .

Vlad Mihalcea
quelle
2

Durch die Verwendung von EntityManager ist Code nicht mehr eng mit dem Ruhezustand verbunden. Aber dafür sollten wir im Gebrauch verwenden:

javax.persistence.EntityManager

anstatt

org.hibernate.ejb.HibernateEntityManager

Verwenden Sie für EntityManagerFactory ebenfalls die Javax-Schnittstelle. Auf diese Weise wird der Code lose gekoppelt. Wenn es eine bessere JPA 2-Implementierung als den Ruhezustand gibt, ist das Wechseln einfach. Im Extremfall könnten wir cast in HibernateEntityManager eingeben.

Sairam Krish
quelle
2

EntityManagerFactory ist die Standardimplementierung und für alle Implementierungen gleich. Wenn Sie Ihr ORM für einen anderen Anbieter wie EclipseLink migrieren, ändert sich der Ansatz für die Abwicklung der Transaktion nicht. Wenn Sie dagegen die Session Factory von Hibernate verwenden, ist diese an APIs für den Ruhezustand gebunden und kann nicht auf einen neuen Anbieter migriert werden.

AUFENTHALT
quelle
1

Die EntityManager-Oberfläche ähnelt der sessionFactory im Ruhezustand. EntityManager unter dem Paket javax.persistance, aber session und sessionFactory unter dem Paket org.hibernate.Session / sessionFactory.

Der Entity Manager ist JPA-spezifisch und session / sessionFactory sind hibernate-spezifisch.

Avvappa Hegadyal
quelle
Ihre Antwort ist richtig, aber im Wesentlichen dieselbe wie die Antwort, auf die Sangyun Lee in seinen Kommentaren verweist ... also ein Duplikat.
RWC