Hibernate SessionFactory vs. JPA EntityManagerFactory

151,661

Solution 1

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

Solution 2

SessionFactory vs. EntityManagerFactory

As I explained in the Hibernate User Guide, the Hibernate SessionFactory extends the JPA EntityManagerFactory, as illustrated by the following diagram:

JPA and Hibernate relationship

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.

Hibernate vs. JPA bootstrap

When bootstrapping a JPA or Hibernate application, you have two choices:

  1. You can bootstrap via the Hibernate native mechanism, and create a SessionFactory via the BootstrapServiceRegistryBuilder. If you're using Spring, the Hibernate bootstrap is done via the LocalSessionFactoryBean, as illustrated by this GitHub example.
  2. Or, you can create a JPA 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.

Unwrapping JPA to Hibernate

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

Conclusion

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.

Solution 3

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

Solution 4

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.

Solution 5

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

Share:
151,661

Related videos on Youtube

elpisu
Author by

elpisu

Updated on January 10, 2021

Comments

  • elpisu
    elpisu over 3 years

    I am new to Hibernate and I'm not sure whether to use a Hibernate SessionFactory or a JPA EntityManagerFactory to create a Hibernate Session.

    What is the difference between these two? What are the pros & cons of using each of those?

  • elpisu
    elpisu about 13 years
    You are a wealth of knowledge! I am just starting out with Hibernate and would like to use Hibernate with JPA Annotations - would you recommend any good resources for a beginner (besides the Hibernate documentation)?
  • Bozho
    Bozho about 13 years
    @elpisu - I can't recommend, actually. I've been using only the official documentation as a learning resource (at least in the past 2 years), so I don't know anything else reliable. But the docs are good enough.
  • manash
    manash over 12 years
    @Bozho I know that it's late but what are the drawbacks of using SessionFactory and Session? Why the use of JPA is preferred? Thanks
  • black sensei
    black sensei over 12 years
    @Bozho please can you elaborate, i also want to know why especially when spring to kinda of going entitymanager with its new spring-data-jpa which uses.What are the drawbacks on sessionFactory.THanks
  • black sensei
    black sensei over 12 years
    Oh sorry, what i mean is data spring-data-jpa is going entityManager way when it comes to hibernate persistence vendor.I wanted to know if that is a significant clue as for going entityManager way as opposed to session way.Thanks
  • László van den Hoek
    László van den Hoek over 11 years
    @MickaelMarrache the use of the JPA is to be preferred over the Hibernate API, because it is a Java Enterprise standard. Using JPA (and restricting yourself to it, without using Hibernate-specific features) improves application portability, i.e. you have the option to switch to a different persistence framework with minimal changes to your application, as long as that framework also conforms to the JPA standard.
  • user1050755
    user1050755 about 11 years
    is it possible to programmatically construct HQL queries using only JPA-covered functionality?
  • ryenus
    ryenus over 9 years
    note that unwrap() is to be preferred over getDelegate() according to the java docs: javaee 6, and javaee 7.
  • Bastian Voigt
    Bastian Voigt about 9 years
    Is it better just because it's an enterprise standard? I doubt that. Standards are usually slow to evolve and complicated. What about some real life benefits? JPA is better because it has TypedQuery, stops you from typecasting all over the place.
  • wst
    wst over 8 years
    You can make any code complicated if you want. return sessionFactory.getCurrentSession().createQuery("from User where id=1").list()
  • Deepu--Java
    Deepu--Java about 6 years
    How directly you got entityManager and you are showing you have to use sessionfactory to fetch session.. :D
  • RWC
    RWC almost 6 years
    Your answer is correct, but is essentially the same as the answer Sangyun Lee refers to in his comments... so a duplicate.
  • Sarvesh
    Sarvesh over 5 years
    Is this approach to get Session from EntityManager, same as SessionFactory.getCurrentSession()? I mean, will it open new Session if it is not already created? How does it work in multithreaded environment?
  • Kumar Manish
    Kumar Manish almost 2 years
    SessionFactory ~= EntityManagerFactory, and NOT EntityManager. Wrong answer.