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?
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?
Respostas:
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);
Sessiona partir EntityManager, mesmo que SessionFactory.getCurrentSession()? Quero dizer, será aberto novamente Sessionse 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 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.
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. EntityManagerFactoryComo expliquei no Guia do Usuário do Hibernate , o Hibernate SessionFactoryestende o JPA EntityManagerFactory, conforme ilustrado pelo diagrama a seguir:
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. EntityManagerAssim 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.
Ao inicializar um aplicativo JPA ou Hibernate, você tem duas opções:
SessionFactoryvia BootstrapServiceRegistryBuilder. Se você estiver usando o Spring, a inicialização do Hibernate é feita através do LocalSessionFactoryBean, conforme ilustrado neste exemplo do GitHub .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 .
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);
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 .
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.