Hibernate SessionFactory vs. JPA EntityManagerFactory


251

Eu sou novo no Hibernate e não tenho certeza se devo usar um Hibernate SessionFactoryou um JPA EntityManagerFactorypara criar um Hibernate Session.

Qual é a diferença entre esses dois? Quais são os prós e os contras de usar cada um deles?


6
Esta resposta em uma pergunta duplicada é realmente boa. stackoverflow.com/questions/23445830/…
Sanghyun Lee

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

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();

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.


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

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 .


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.


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.


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.


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.