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.