Hibernate SessionFactory vs. JPA EntityManagerFactory

Respostas:

365

Prefere EntityManagerFactorye EntityManager. Eles são definidos pelo padrão JPA.

SessionFactorye Sessionsão específicos do hibernate. A EntityManagerinvoca a sessão de hibernação sob o capô. E se você precisar de alguns recursos específicos que não estão disponíveis no EntityManager, poderá obter a sessão chamando:

Session session = entityManager.unwrap(Session.class);
Bozho
fonte
2
@elpisu - na verdade não posso recomendar. Eu tenho usado apenas a documentação oficial como recurso de aprendizado (pelo menos nos últimos 2 anos), por isso não conheço mais nada confiável. Mas os documentos são bons o suficiente.
Bozho
7
@Bozho Eu sei que é tarde, mas quais são as desvantagens de usar o SessionFactory e o Session? Por que o uso da JPA é preferido? Obrigado
Mickael Marrache 11/11
12
@MickaelMarrache, o uso do JPA deve ser preferido em relação à API do Hibernate, porque é um padrão Java Enterprise. Usar o JPA (e restringir-se a ele, sem usar recursos específicos do Hibernate) melhora a portabilidade do aplicativo, ou seja, você tem a opção de alternar para uma estrutura de persistência diferente com alterações mínimas no seu aplicativo, desde que essa estrutura também esteja em conformidade com o padrão JPA .
László van den Hoek
2
É melhor apenas porque é um padrão corporativo? Eu duvido disso. Os padrões geralmente demoram a evoluir e são complicados. E alguns benefícios da vida real? O JPA é melhor porque possui o TypedQuery, impedindo que você faça a digitação em todo o lugar.
Bastian Voigt
1
É esta abordagem para obter Sessiona partir EntityManager, mesmo que SessionFactory.getCurrentSession()? Quero dizer, será aberto novamente Sessionse ainda não estiver criado? Como funciona em ambiente multithread?
Sarvesh 17/09/18
32

Quero acrescentar que você também pode obter a sessão do Hibernate chamando o getDelegate()método EntityManager.

ex:

Session session = (Session) entityManager.getDelegate();
toytoy
fonte
28
nota que unwrap()é para ser preferido sobre getDelegate()acordo com os documentos java: javaee 6 , e javaee 7 .
ryenus
22

Eu prefiro a EntityManagerAPI JPA2 ao invés SessionFactory, porque parece mais moderna. Um exemplo simples:

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

Acho claro que o primeiro parece mais limpo e também é mais fácil de testar, porque o EntityManager pode ser facilmente ridicularizado.

Bastian Voigt
fonte
30
Você pode complicar qualquer código, se quiser. return sessionFactory.getCurrentSession().createQuery("from User where id=1").list()
wst
Como directamente você tem entityManager e você está mostrando que você tem que usar SessionFactory para buscar sessão ..: D
JavaLearner
21

O uso da abordagem EntityManagerFactory nos permite usar anotações de método de retorno de chamada como @PrePersist, @ PostPersist, @ PreUpdate sem configuração extra.

Usar retornos de chamada semelhantes ao usar o SessionFactory exigirá esforços extras.

Documentos relacionados do Hibernate podem ser encontrados aqui e aqui .

Questões SOF relacionadas e discussão no Fórum da Primavera

Kumar Sambhav
fonte
21

SessionFactory vs. EntityManagerFactory

Como expliquei no Guia do Usuário do Hibernate , o Hibernate SessionFactoryestende o JPA EntityManagerFactory, conforme ilustrado pelo diagrama a seguir:

Relação JPA e Hibernate

Portanto, o SessionFactorytambém é um JPA EntityManagerFactory.

Tanto o SessionFactoryeo EntityManagerFactorycontêm os metadados de mapeamento entidade e permitir-lhe criar um Hibernate Sessionou um EntityManager.

Session vs. EntityManager

Assim como o SessionFactorye EntityManagerFactory, o Hibernate Sessionestende o JPA EntityManager. Portanto, todos os métodos definidos por EntityManagerestão disponíveis no Hibernate Session.

O Sessione o `EntityManager convertem transições de estado da entidade em instruções SQL, como SELECT, INSERT, UPDATE e DELETE.

Bootstrap Hibernate vs. JPA

Ao inicializar um aplicativo JPA ou Hibernate, você tem duas opções:

  1. Você pode inicializar através do mecanismo nativo do Hibernate e criar um SessionFactoryvia BootstrapServiceRegistryBuilder. Se você estiver usando o Spring, a inicialização do Hibernate é feita através do LocalSessionFactoryBean, conforme ilustrado neste exemplo do GitHub .
  2. Ou, você pode criar um JPA EntityManagerFactoryatravés da Persistenceclasse ou doEntityManagerFactoryBuilder . Se você estiver usando o Spring, a inicialização do JPA será feita via LocalContainerEntityManagerFactoryBean, conforme ilustrado neste exemplo do GitHub .

O bootstrapping via JPA é o preferido. Isso porque o JPAFlushModeType.AUTO ocorre é uma escolha muito melhor do que o legado FlushMode.AUTO, que quebra a consistência de leitura e gravação para consultas SQL nativas .

Desembrulhando o JPA no Hibernate

Além disso, se você inicializar via JPA e tiver injetado o EntityManagerFactory via @PersistenceUnitanotação:

@PersistenceUnit
private EntityManagerFactory entityManagerFactory;

Você pode obter facilmente acesso ao subjacente Sessionfactory usando o unwrapmétodo:

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

O mesmo pode ser feito com o JPA EntityManager. Se você injetar oEntityManager via @PersistenceContextanotação:

@PersistenceContext
private EntityManager entityManager;

Você pode obter facilmente acesso ao subjacente Session usando o unwrapmétodo:

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

Conclusão

Portanto, você deve autoinicializar via JPA, usar as teclas EntityManagerFactorye EntityManager, e somente desembrulhá-las nas interfaces associadas do Hibernate quando desejar obter acesso a alguns métodos específicos do Hibernate que não estão disponíveis na JPA, como buscar a entidade por meio de seu identificador natural .

Vlad Mihalcea
fonte
2

Ao usar o EntityManager, o código não está mais fortemente associado ao hibernate. Mas para isso, em uso, devemos usar:

javax.persistence.EntityManager

ao invés de

org.hibernate.ejb.HibernateEntityManager

Da mesma forma, para EntityManagerFactory, use a interface javax. Dessa forma, o código é fracamente acoplado. Se houver uma implementação JPA 2 melhor que a hibernação, a troca seria fácil. Em casos extremos, podemos digitar cast para HibernateEntityManager.

Sairam Krish
fonte
2

EntityManagerFactory é a implementação padrão, é a mesma em todas as implementações. Se você migrar seu ORM para qualquer outro provedor como o EclipseLink, não haverá nenhuma mudança na abordagem para lidar com a transação. Por outro lado, se você usar o factory de sessão do hibernate, ele estará vinculado às APIs do hibernate e não poderá migrar para o novo fornecedor.

ABODE
fonte
1

A interface do EntityManager é semelhante à sessionFactory no hibernate. EntityManager no pacote javax.persistance, mas session e sessionFactory no pacote org.hibernate.Session / sessionFactory.

O gerenciador de entidades é específico para JPA e session / sessionFactory é específico para hibernação.

Avvappa Hegadyal
fonte
Sua resposta está correta, mas é essencialmente a mesma que a resposta a que Sangyun Lee se refere nos comentários dele ... portanto, uma duplicata.
RWC 24/07