Hibernate SessionFactory vs. JPA EntityManagerFactory

Respuestas:

365

Prefiero EntityManagerFactoryy EntityManager. Están definidos por el estándar JPA.

SessionFactoryy Sessionson específicos de hibernación. El EntityManagerinvoca la sesión de hibernación bajo el capó. Y si necesita algunas características específicas que no están disponibles en el EntityManager, puede obtener la sesión llamando a:

Session session = entityManager.unwrap(Session.class);
Bozho
fuente
2
@elpisu - No puedo recomendar, en realidad. He estado usando solo la documentación oficial como recurso de aprendizaje (al menos en los últimos 2 años), por lo que no sé nada más confiable. Pero los documentos son lo suficientemente buenos.
Bozho
77
@Bozho Sé que es tarde, pero ¿cuáles son los inconvenientes de usar SessionFactory y Session? ¿Por qué se prefiere el uso de JPA? Gracias
Mickael Marrache
12
@MickaelMarrache, el uso de JPA es preferible a la API de Hibernate, porque es un estándar Java Enterprise. El uso de JPA (y restringirse a él, sin usar características específicas de Hibernate) mejora la portabilidad de la aplicación, es decir, tiene la opción de cambiar a un marco de persistencia diferente con cambios mínimos en su aplicación, siempre que ese marco también se ajuste al estándar JPA .
László van den Hoek
2
¿Es mejor solo porque es un estándar empresarial? Dudo que. Los estándares suelen evolucionar lentamente y son complicados. ¿Qué pasa con algunos beneficios de la vida real? JPA es mejor porque tiene TypedQuery, le impide escribir en todo el lugar.
Bastian Voigt
1
Es este enfoque para llegar Sessiondesde EntityManager, al igual que SessionFactory.getCurrentSession()? Quiero decir, ¿se abrirá nuevo Sessionsi aún no se ha creado? ¿Cómo funciona en un entorno multiproceso?
Sarvesh
32

Quiero agregar a esto que también puede obtener la sesión de Hibernate llamando al getDelegate()método desdeEntityManager .

ex:

Session session = (Session) entityManager.getDelegate();
juguete
fuente
28
nota que unwrap()es que se prefiere más de getDelegate()acuerdo con los documentos de Java: JavaEE 6 , y JavaEE 7 .
ryenus
22

Prefiero la EntityManagerAPI JPA2 sobre SessionFactory, porque se siente más moderna. Un ejemplo 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;
}

Creo que está claro que el primero se ve más limpio y también es más fácil de probar porque EntityManager se puede burlar fácilmente.

Bastian Voigt
fuente
30
Puede complicar cualquier código si lo desea. return sessionFactory.getCurrentSession().createQuery("from User where id=1").list()
wst
Cuán directamente obtuviste entityManager y estás mostrando que tienes que usar sessionfactory para recuperar la sesión ..: D
JavaLearner
21

El uso del enfoque EntityManagerFactory nos permite usar anotaciones de métodos de devolución de llamada como @PrePersist, @ PostPersist, @ PreUpdate sin configuración adicional.

Usar devoluciones de llamada similares al usar SessionFactory requerirá esfuerzos adicionales.

Los documentos relacionados de Hibernate se pueden encontrar aquí y aquí .

Preguntas relacionadas con SOF y discusión en el foro de primavera

Kumar Sambhav
fuente
21

SessionFactory vs. EntityManagerFactory

Como expliqué en la Guía del usuario de Hibernate , Hibernate SessionFactoryextiende la JPA EntityManagerFactory, como se ilustra en el siguiente diagrama:

Relación JPA e Hibernate

Entonces, SessionFactorytambién es un JPA EntityManagerFactory.

Tanto el SessionFactoryy el EntityManagerFactorycontienen los metadatos de mapeo de la entidad y le permiten crear un Hibernate Sessiono un EntityManager.

Session vs. EntityManager

Al igual que el SessionFactoryy EntityManagerFactory, el Hibernate Sessionextiende el JPA EntityManager. Por lo tanto, todos los métodos definidos por el EntityManagerestán disponibles en HibernateSession .

El Sessiony el `EntityManager traducen las transiciones de estado de la entidad en instrucciones SQL, como SELECT, INSERT, UPDATE y DELETE.

Hibernate vs JPA bootstrap

Al iniciar una aplicación JPA o Hibernate, tiene dos opciones:

  1. Puede iniciar mediante el mecanismo nativo de Hibernate y crear una SessionFactoryvía BootstrapServiceRegistryBuilder. Si está utilizando Spring, la rutina de arranque de Hibernate se realiza a través de LocalSessionFactoryBean, como se ilustra en este ejemplo de GitHub .
  2. O bien, puede crear un JPA a EntityManagerFactorytravés de la Persistenceclase o el EntityManagerFactoryBuilder. Si está utilizando Spring, el bootstrap JPA se realiza a través de LocalContainerEntityManagerFactoryBean, como se ilustra en este ejemplo de GitHub .

Se prefiere el bootstrapping a través de JPA. Esto se debe a que JPA FlushModeType.AUTOes una opción mucho mejor que el legado FlushMode.AUTO, que rompe la coherencia de lectura y escritura para consultas SQL nativas .

Desenvolviendo JPA para Hibernar

Además, si arranca a través de JPA y ha inyectado a EntityManagerFactorytravés de la @PersistenceUnitanotación:

@PersistenceUnit
private EntityManagerFactory entityManagerFactory;

Puede acceder fácilmente al subyacente Sessionfactoryutilizando el unwrapmétodo:

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

Lo mismo se puede hacer con el JPA EntityManager. Si inyecta el a EntityManagertravés de la @PersistenceContextanotación:

@PersistenceContext
private EntityManager entityManager;

Puede acceder fácilmente al subyacente Sessionutilizando el unwrapmétodo:

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

Conclusión

Por lo tanto, debe iniciar a través de JPA, usar el EntityManagerFactoryy EntityManager, y solo desenvolverlos en sus interfaces de Hibernate asociadas cuando desee obtener acceso a algunos métodos específicos de Hibernate que no están disponibles en JPA, como obtener la entidad a través de su identificador natural .

Vlad Mihalcea
fuente
2

Al usar EntityManager, el código ya no está estrechamente vinculado con la hibernación. Pero para esto, en el uso debemos usar:

javax.persistence.EntityManager

en vez de

org.hibernate.ejb.HibernateEntityManager

Del mismo modo, para EntityManagerFactory, use la interfaz javax. De esa manera, el código está débilmente acoplado. Si hay una mejor implementación de JPA 2 que hibernar, el cambio sería fácil. En casos extremos, podríamos escribir cast en HibernateEntityManager.

Sairam Krish
fuente
2

EntityManagerFactory es la implementación estándar, es la misma en todas las implementaciones. Si migra su ORM para cualquier otro proveedor como EclipseLink, no habrá ningún cambio en el enfoque para manejar la transacción. Por el contrario, si usa la fábrica de sesiones de hibernate, está vinculada a las API de hibernate y no puede migrar a un nuevo proveedor.

MORADA
fuente
1

La interfaz EntityManager es similar a sessionFactory en hibernación. EntityManager bajo el paquete javax.persistance pero session y sessionFactory bajo el paquete org.hibernate.Session / sessionFactory.

El gestor de entidades es específico de JPA y session / sessionFactory es específico de hibernación.

Avvappa Hegadyal
fuente
Su respuesta es correcta, pero es esencialmente la misma que la respuesta a la que se refiere Sangyun Lee en sus comentarios ... así que es un duplicado.
RWC