3

Context of Multi-Thread environment like web app, whenever required to use sessions using Hibernate what would be the best way to get session either getcurrentsession() or opensession() ?

As on here opensession vs getcurrentsession it has mentioned that getcurrentsession is not to be use in web applications.

While session is not tread-safe, due to that reason isn't it suits for use getcurrentsession ? Is it need to use opensesion and commit & close flush manually ?

I need a clear clarification. Thanks All.

PS : I used hibernate with Spring Boot App for testing purpose.

GrootC
  • 113
  • 2
  • 10

1 Answers1

4

If you have spring-boot-autocofigure in your classpath, chances are it is already configuring an EntityManagerFactory for you. If you don't have that on your classpath, its super easy to convert your bean configuration for a SessionFactory to an EntityManagerFactory. After having done that, you can get an instance super simply by doing the following in your spring bean

@Service
public class MyBookServiceImpl implements BookService {
  @PersistenceContext
  private EntityManager entityManager;

  @Transactional
  public void doSomeFancyHibernateThing() {
    List<Book> allBooks = entityManager.createQuery( "FROM Book", Book.class )
       .getResultList();
  }
}

At this point you can add whatever methods to the service class you need to do whatever tasks are required for that bean to fulfill and work with an instance of an EntityManager. You do not need to be concerned with multiple threads, etc because spring automatically gives you an instance of the EntityManager that is safe to use in that thread without concern with other threads.

Note I say here safe to use in that thread. Do not attempt to use that instance in another thread and expect there not to be complications or problems.

If you feel you must use a SessionFactory for whatever reason you can use either of the two methods depending on how much you want to manage the lifecycle of a session.

If you want to use #getCurrentSession(), its important that you also provide hibernate the following configuration so that it binds the current session lookup against a thread-local variable making sure that each thread gives its own session object:

hibernate.current_session_context_class=thread

The benefit to using the above is that you do not need to worry about the lifecycle management of a Session, it will automatically be closed & released when your transaction ends.

For example:

@Transactional
public void doSomeFancyHibernateThing() {
  Session session = sessionFactory.getCurrentSession();
  // do something here, when the method exits, the session is closed & destroyed.
}

If you want to use #openSession(), then the lifecycle and lifetime of the returned Session object is on you to guarantee you deal with closing its resources appropriately. In other words, the above simple method becomes this:

public void doSomeFancyHibernateThing() {
  Session session = sessionFactory.openSession();
  try {
     // do something here
  }
  catch ( Exception e ) {
     // do whatever
  }
  finally {
    if ( session != null && session.isOpen() ) {
      session.close();
    }
  }
}

As you can see, the JPA equivalent at the top of the answer is very similar to the use of getCurrentSession() when paired with that one hibernate configuration.

The strong benefit again here is that using JPA (the example at the top) removes any and all dependencies on Hibernate directly. And if you find you run into a use case where you need Hibernate-specific features that JPA does not expose, you can still easily get a Session by unwrapping the EntityManager as follows:

Session session = entityManager.unwrap( Session.class );
// do whatever you need with a session easily.
Naros
  • 19,928
  • 3
  • 41
  • 71
  • Thanks for your explanation. As your answer, Is it good idea to use ` #getcurrentsession() ` in a web application ? I have seen that hibernate tutorials mentioned as clearly not to use ` #getcurrentsession() ` kind of webapplication context. Btw from your answer I feel that it is not issue if use ` #getcurrentsession() ` in web application. Is it correct ? – GrootC Jun 02 '18 at 20:01
  • My answer covered that. You **can** use it but only if you set that specific configuration property. If you do not, it will create problems. It's generally accepted practice to let Spring provide you what you need as a big reason to use Spring is to let it handle a lot of the mundane boilerplate stuff for you so you can focus on your application's needs. – Naros Jun 02 '18 at 20:08
  • Thanks mate. Those tutorials are incorrect I think. [Check Link](https://www.journaldev.com/3522/hibernate-sessionfactory) You can check in here it said not to use getcurrentsession even hibernate.current_session_context_class=thread configuration. Thanks for help – GrootC Jun 02 '18 at 20:16
  • No it doesn't. Its pointing out that a `Session` is not thread-safe and therefore you should not share it across thread boundaries. No where does it say you cannot use `#getCurrentSession()` in a multi-threaded environment. It does specifically say if you wish to do that, you should set that configuration property to `thread` for it to work properly. – Naros Jun 02 '18 at 20:35
  • Thanks @Naros I can clearly understand now. By both approach can be implement session-per-request pattern in multi-thread environment with particular config way (only for `getcurrentsession`). – GrootC Jun 03 '18 at 04:55