Get Session From EntityManager in Spring Boot

Consider a scenario, we have Spring Boot Application and we need session object to perform some specific operation. In order to access Hibernate APIs(for example Session methods) from JPA, we need a session object from EntityManager. In this post, we will see How To get Hibernate Session From EntityManager in Spring Boot with Example.

First we will get EntityManger using PersitentContext then we will get Hibernate session using entityManager.

Getting Session using entityManger.unwrap() method

JPA EntityManger has unwrap() method with below signature.

public T unwrap(Class class)

We can pass Session interface as a parameter and get Session object.

@Transactional
public Student usingUnwrap(Long id) {

    // Getting Session using entityManger.unwrap() method.
    Session session = entityManager.unwrap(Session.class);
    Student student = session.get(Student.class, id);
    return student;
}

Getting Session using entityManger.getDelegate() method

We can also get Session object using entityManager.getDelegate() method.

@Transactional
public Student usingGetDelegate(Long id) {

    // Getting Session using entityManger.getDelegate() method.
    Session session = (Session) entityManager.getDelegate();
    Student student = session.get(Student.class, id);
    return student;
}

Difference between getting Session using entityManager.getDelagate() and entityManager.unwrap() method

EntityManager getDelegate().

What EntityManager’s getDelegate() will returns it depends on implementation class (For example in our case SessionImpl.java is implementation class for EntityManager getDelegate() method. If we look impementation of getDelegate() method in SessionImpl.java class, it is just returning this i.e session object).

@Override
public Object getDelegate() {
    return this;
}

The getDelegate() method introduced in JPA 1.0.

EntityManager unwrap().

EntityManager’s unwrap() method returns an object of the specified type to allow access to the provider-specific API. The unwrap() method (overridden in SessionImpl.java) first checks the session is closed or not. If Session is closed, it throws java.lang.IllegalStateException.

If Session is closed and then we call getDelegate() method, it will not throw any exception.

Below code snnipet(unwrap() method) will throw exception.

@Transactional
public Student usingUnwrap(Long id) {

    // Getting Session using entityManger.unwrap() method.
    Session session = entityManager.unwrap(Session.class);
    session.close();
    session = entityManager.unwrap(Session.class);
    Student student = session.get(Student.class, id);
    return student;
}

java.lang.IllegalStateException: Session/EntityManager is closed
at org.hibernate.internal.AbstractSharedSessionContract.checkOpen(AbstractSharedSessionContract.java:344) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]

Below code snippet will not throw any exception.

@Transactional
public Student usingGetDelegate(Long id) {

    // Getting Session using entityManger.getDelegate() method.
    Session session = entityManager.unwrap(Session.class);
    session.close();
    session = (Session) entityManager.getDelegate();
    Student student = session.get(Student.class, id);
    return student;
}

The unwrap() method perform isAssignableFrom() checks for Session, SessionImplementor, SharedSessionContractImplementor, and EntityManager interfaces with passed argument.

EntityManager’s unwrap() method introduced in JPA 2.0.

How unwrap() method is implemented in SessionImpl.java class

@Override
public T unwrap(Class class) {
    checkOpen();

    if ( Session.class.isAssignableFrom( class) ) {
        return (T) this;
    }
    // Some more code 
}

While using unwrap() method, if the passing parameter is not able to convert the corresponding type then it will throw javax.persistence.PersistenceException.

For example below code will throw javax.persistence.PersistenceException.

SessionFactory sessionFactory = entityManager.unwrap(SessionFactory.class);

javax.persistence.PersistenceException: Hibernate cannot unwrap interface org.hibernate.SessionFactory
at org.hibernate.internal.SessionImpl.unwrap(SessionImpl.java:3841) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]

But we can get SessionFactory using EntityManagerFactory inetrface. First we need to get EntityManagerfactory using EntityManager and then we need to call unwrap() method.

SessionFactory sessionFactory = entityManager.getEntityManagerFactory().unwrap( SessionFactory.class );

Get Hibernate Session in Spring Boot from EntityManagerFactory

We can configure Session using @Bean annotation.

package com.javatute.config;

import javax.persistence.EntityManagerFactory;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JpaConfig {

	@Autowired
	private EntityManagerFactory entityManagerFactory;

	@Bean
	public Session getSession() {
		SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
		Session session = sessionFactory.openSession();
		return session;

	}
}

Now we will get Session object using @Autowired annotation.

package com.javatute.serviceimpl;

import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.javatute.entity.Student;
import com.javatute.service.StudentService;

@Service
public class StudentServiceImpl implements StudentService {

	@Autowired
	private Session session;

	@Transactional
	public Student save(Student student) {
		session.persist(student);
		return student;
	}

	@Transactional
	public Student retrieve(Long id) {
		Student student = session.get(Student.class, id);
		return student;
	}

}

JPA Entitymanager vs Hibernate Session

In this section we will see What are the differences between JPA EntityManager and Hibernate Session.

JPA EntityManagerHibernate Session
JPA EntityManager interface is available in javax.persistence package and introduced in JPA 1.0. Session interface is available in org.hibernate package.
EntityManager can be implemented by other framework like EclipseLink or TopLink or Hibernate.The Session is Hibernate specific.
EntityManager is a parent interface.Session interafce extends EntityManager interface.
EntityManager provides different methods like persist(), merge(), find() and delete() to perform CRUD operartion.Hibernate Session provides save(), update(), get()/load() and delete() to perform CRUD operation.
We can get EntityManager from the session as below.
EntityManager em = session.getEntityManagerFactory().createEntityManager();
We can get session from EntityManger using unwrap() method. We have already seen.

Note – We can get EntityManger from Hibernate session using EntityManagerFactory. First, we will create EntityManagerFactory, the EntityManagerFactory has createEntityManager() method, using that we can get EntityManger.

public Student getStudent(Long id) {
	SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
	Session session = sessionFactory.openSession();
	EntityManager em = session.getEntityManagerFactory().createEntityManager();
	return em.find(Student.class, id);
}

Get Hibernate Session from JPA EntityManager example Using Spring Boot

Open eclipse and create maven project, Don’t forget to check ‘Create a simple project (skip)’ and click on next. Fill all details(GroupId – getsessionfromentitymanger, ArtifactId – getsessionfromentitymanger and name – getsessionfromentitymanger) and click on finish. Keep packaging as the jar.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>getsessionfromentitymanger</groupId>
	<artifactId>getsessionfromentitymanger</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>getsessionfromentitymanger</name>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.2.RELEASE</version>
	</parent>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
	</dependencies>
</project>

Example directory.

Get Session From EntityManager

Define Entity and other classes/interfaces.

Student.java

package com.javatute.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Student {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	@Column(name = "name")
	private String name;

	@Column(name = "roll_number")
	private String rollNumber;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getRollNumber() {
		return rollNumber;
	}

	public void setRollNumber(String rollNumber) {
		this.rollNumber = rollNumber;
	}

}

StudentService.java

package com.javatute.service;

import org.springframework.stereotype.Component;

import com.javatute.entity.Student;

@Component
public interface StudentService {

	public Student save(Student student);

	public Student usingUnwrap(Long id);

	public Student usingGetDelegate(Long id);
}

StudentRepository.java

package com.springboothql.repository;

import java.io.Serializable;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.springboothql.entity.Student;

@Repository
public interface StudentRepository extends JpaRepository<Student, Serializable> {

}

StudentServiceImpl.java

package com.javatute.serviceimpl;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.hibernate.Session;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.javatute.entity.Student;
import com.javatute.service.StudentService;

@Service
public class StudentServiceImpl implements StudentService {

	@PersistenceContext
	private EntityManager entityManager;

	@Transactional
	public Student save(Student student) {
		entityManager.persist(student);
		return student;
	}

	@Transactional
	public Student usingUnwrap(Long id) {

		// Getting Session using entityManger.unwrap() method.
		Session session = entityManager.unwrap(Session.class);
		Student student = session.get(Student.class, id);
		return student;
	}

	@Transactional
	public Student usingGetDelegate(Long id) {

		// Getting Session using entityManger.getDelegate() method.
		Session session = (Session) entityManager.getDelegate();
		Student student = session.get(Student.class, id);
		return student;
	}
}

StudentController.java

package com.javatute.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.javatute.entity.Student;
import com.javatute.service.StudentService;

@RestController
@RequestMapping("/student")
public class StudentController {

	@Autowired
	private StudentService studentService;

	@PostMapping("/create")
	public Student createStudent(@RequestBody Student student) {
		Student createResponse = studentService.save(student);
		return createResponse;
	}

	@GetMapping("/usingunwrap/{id}")
	public Student usingUnwrap(@PathVariable Long id) {
		Student getReponse = studentService.usingUnwrap(id);
		return getReponse;
	}

	@GetMapping("/usinggetdelegate/{id}")
	public Student usingGetDelegate(@PathVariable Long id) {
		Student getReponse = studentService.usingGetDelegate(id);
		return getReponse;
	}
}

SpringMain.java

package com.javatute.main;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan(basePackages = "com.javatute.*")
@EntityScan("com.javatute.*")
public class SpringMain {
	public static void main(String[] args) {
		SpringApplication.run(SpringMain.class, args);
	}
}

JpaConfig.java

package com.springboothql.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@Configuration
@EnableJpaRepositories(basePackages = "com.javatute.repository")
public class JpaConfig {

}

application.yml

spring:
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: create
  datasource:
    url: jdbc:mysql://localhost:3306/springbootcrudexample
    username: root
    password: root
server:
   port: 9091       

Let’s run the example and test below APIs using postman.

localhost:9091/student/create

How to get Session From JPA EntityManager

localhost:9091/student/usingunwrap/1

localhost:9091/student/usinggetdelegate/1

How to get Session From EntityManager

That’s all about how to get session from entitymanager.

Related article.

You may like.

Hibernate/JPA association and inheritance mapping.

See EntityManager docs here.

Hibernate Session docs.

Sumary – We have seen how to get Session from EntityManager to access Hibernate APIs from JPA.