Eu sou novo no Hibernate e não tenho certeza se devo usar um Hibernate SessionFactory
ou um JPA EntityManagerFactory
para 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?
Eu sou novo no Hibernate e não tenho certeza se devo usar um Hibernate SessionFactory
ou um JPA EntityManagerFactory
para 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?
Respostas:
Prefere EntityManagerFactory
e EntityManager
. Eles são definidos pelo padrão JPA.
SessionFactory
e Session
são específicos do hibernate. A EntityManager
invoca 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);
Session
a partir EntityManager
, mesmo que SessionFactory.getCurrentSession()
? Quero dizer, será aberto novamente Session
se ainda não estiver criado? Como funciona em ambiente multithread?
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();
Eu prefiro a EntityManager
API 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.
return sessionFactory.getCurrentSession().createQuery("from User where id=1").list()
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 .
SessionFactory
vs. EntityManagerFactory
Como expliquei no Guia do Usuário do Hibernate , o Hibernate SessionFactory
estende o JPA EntityManagerFactory
, conforme ilustrado pelo diagrama a seguir:
Portanto, o SessionFactory
também é um JPA EntityManagerFactory
.
Tanto o SessionFactory
eo EntityManagerFactory
contêm os metadados de mapeamento entidade e permitir-lhe criar um Hibernate Session
ou um EntityManager
.
Session
vs. EntityManager
Assim como o SessionFactory
e EntityManagerFactory
, o Hibernate Session
estende o JPA EntityManager
. Portanto, todos os métodos definidos por EntityManager
estão disponíveis no Hibernate Session
.
O Session
e o `EntityManager convertem transições de estado da entidade em instruções SQL, como SELECT, INSERT, UPDATE e DELETE.
Ao inicializar um aplicativo JPA ou Hibernate, você tem duas opções:
SessionFactory
via BootstrapServiceRegistryBuilder
. Se você estiver usando o Spring, a inicialização do Hibernate é feita através do LocalSessionFactoryBean
, conforme ilustrado neste exemplo do GitHub .EntityManagerFactory
através da Persistence
classe 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 .
Além disso, se você inicializar via JPA e tiver injetado o EntityManagerFactory
via @PersistenceUnit
anotação:
@PersistenceUnit
private EntityManagerFactory entityManagerFactory;
Você pode obter facilmente acesso ao subjacente Sessionfactory
usando o unwrap
método:
SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
O mesmo pode ser feito com o JPA EntityManager
. Se você injetar oEntityManager
via @PersistenceContext
anotação:
@PersistenceContext
private EntityManager entityManager;
Você pode obter facilmente acesso ao subjacente Session
usando o unwrap
método:
Session session = entityManager.unwrap(Session.class);
Portanto, você deve autoinicializar via JPA, usar as teclas EntityManagerFactory
e 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 .
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.
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.
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.