Hibernate SessionFactory frente a JPA EntityManagerFactory

Resuelto elpisu asked hace 13 años • 8 respuestas

Soy nuevo en Hibernate y no estoy seguro de si debo usar Hibernate SessionFactoryo JPA EntityManagerFactorypara crear un Hibernate Session.

¿Cuál es la diferencia entre estos dos? ¿Cuáles son las ventajas y desventajas de usar cada uno de ellos?

elpisu avatar Apr 13 '11 02:04 elpisu
Aceptado

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

SessionFactoryy Sessionson específicos de hibernación. Invoca EntityManagerla sesión de hibernación bajo el capó. Y si necesitas algunas funcionalidades específicas que no están disponibles en el EntityManager, puedes obtener la sesión llamando a:

Session session = entityManager.unwrap(Session.class);
Bozho avatar Apr 12 '2011 19:04 Bozho

SessionFactoryvs.EntityManagerFactory

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

Relación JPA e Hibernate

Entonces, SessionFactorytambién es un JPA EntityManagerFactory.

Tanto el SessionFactorycomo el EntityManagerFactorycontienen los metadatos de mapeo de entidades y le permiten crear un Hibernate Sessiono un EntityManager.

Sessionvs.EntityManager

Al igual que SessionFactoryy EntityManagerFactory, Hibernate Sessionextiende el JPA EntityManager. Entonces, todos los métodos definidos por EntityManagerestán disponibles en Hibernate Session.

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

Hibernación frente a arranque JPA

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

  1. Puede iniciar a través del mecanismo nativo de Hibernate y crear un archivo SessionFactorya través del archivo BootstrapServiceRegistryBuilder. Si está utilizando Spring, el arranque de Hibernate se realiza a través de LocalSessionFactoryBean, como se ilustra en este ejemplo de GitHub .
  2. O puede crear un JPA EntityManagerFactorya través de la Persistenceclase o el archivo EntityManagerFactoryBuilder. Si está utilizando Spring, el arranque de JPA se realiza a través de LocalContainerEntityManagerFactoryBean, como se ilustra en este ejemplo de GitHub .

Se prefiere el arranque 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 inicia a través de JPA y ha inyectado a EntityManagerFactorytravés de la @PersistenceUnitanotación:

@PersistenceUnit
private EntityManagerFactory entityManagerFactory;

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

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

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

@PersistenceContext
private EntityManager entityManager;

Puede obtener acceso 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 EntityManagerFactoryy EntityManagery 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 buscar la entidad a través de su identificador natural .

Vlad Mihalcea avatar Feb 22 '2020 17:02 Vlad Mihalcea

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

ex:

Session session = (Session) entityManager.getDelegate();
toytoy avatar Jan 19 '2013 06:01 toytoy

Prefiero la EntityManagerAPI JPA2 a SessionFactory, porque parece más moderna. Un ejemplo sencillo:

APP:

@PersistenceContext
EntityManager entityManager;

public List<MyEntity> findSomeApples() {
  return entityManager
     .createQuery("from MyEntity where apples=7", MyEntity.class)
     .getResultList();
}

Fábrica de sesiones:

@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 parece más limpio y también es más fácil de probar porque se puede burlar fácilmente de EntityManager.

Bastian Voigt avatar Mar 04 '2015 08:03 Bastian Voigt