Prefer EntityManagerFactory and EntityManager. They are defined by the JPA standard.
SessionFactory and Session are hibernate-specific. The EntityManager invokes the hibernate session under the hood. And if you need some specific features that are not available in the EntityManager, you can obtain the session by calling:
Session session = entityManager.unwrap(Session.class);
SessionFactory vs. EntityManagerFactory
As I explained in the Hibernate User Guide, the Hibernate SessionFactory extends the JPA EntityManagerFactory, as illustrated by the following diagram:

So, the SessionFactory is also a JPA EntityManagerFactory.
Both the SessionFactory and the EntityManagerFactory contain the entity mapping metadata and allow you to create a Hibernate Session or a EntityManager.
Session vs. EntityManager
Just like the SessionFactory and EntityManagerFactory, the Hibernate Session extends the JPA EntityManager. So, all methods defined by the EntityManager are available in the Hibernate Session.
The Session and the `EntityManager translate entity state transitions into SQL statements, like SELECT, INSERT, UPDATE, and DELETE.
When bootstrapping a JPA or Hibernate application, you have two choices:
SessionFactory via the BootstrapServiceRegistryBuilder. If you're using Spring, the Hibernate bootstrap is done via the LocalSessionFactoryBean, as illustrated by this GitHub example.EntityManagerFactory via the Persistence class or the EntityManagerFactoryBuilder. If you're using Spring, the JPA bootstrap is done via the LocalContainerEntityManagerFactoryBean, as illustrated by this GitHub example.Bootstrapping via JPA is to be preferred. That's because the JPA FlushModeType.AUTO is a much better choice than the legacy FlushMode.AUTO, which breaks read-your-writes consistency for native SQL queries.
Also, if you bootstrap via JPA, and you have injected the EntityManagerFactory via the @PersistenceUnit annotation:
@PersistenceUnit
private EntityManagerFactory entityManagerFactory;
You can easily get access to the underlying Sessionfactory using the unwrap method:
SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
The same can be done with the JPA EntityManager. If you inject the EntityManager via the @PersistenceContext annotation:
@PersistenceContext
private EntityManager entityManager;
You can easily get access to the underlying Session using the unwrap method:
Session session = entityManager.unwrap(Session.class);
So, you should bootstrap via JPA, use the EntityManagerFactory and EntityManager, and only unwrap those to their associated Hibernate interfaces when you want to get access to some Hibernate-specific methods that are not available in JPA, like fetching the entity via its natural identifier.
I want to add on this that you can also get Hibernate's session by calling getDelegate() method from EntityManager.
ex:
Session session = (Session) entityManager.getDelegate();
I prefer the JPA2 EntityManager API over SessionFactory, because it feels more modern. One simple example:
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;
}
I think it's clear that the first one looks cleaner and is also easier to test because EntityManager can be easily mocked.
Using EntityManagerFactory approach allows us to use callback method annotations like @PrePersist, @PostPersist,@PreUpdate with no extra configuration.
Using similar callbacks while using SessionFactory will require extra efforts.
Related Hibernate docs can be found here and here.
Related SOF Question and Spring Forum discussion
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With