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 EntityManager | Hibernate 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.
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
localhost:9091/student/usingunwrap/1
localhost:9091/student/usinggetdelegate/1
That’s all about how to get session from entitymanager.
Related article.
You may like.
- JPA EntityManager CRUD example Using Spring Boot.
- How to get JPA EntityManager in Spring Boot
- Hibernate Eager vs Lazy loading Example.
- JPA Cascade Types example using Spring Boot.
- JPA EntityManager persist() and merge() method.
Hibernate/JPA association and inheritance mapping.
- Hibernate Table Per Concrete Class Spring Boot.
- Hibernate Table Per Subclass Inheritance Spring Boot.
- Hibernate Single Table Inheritance using Spring Boot.
- One To One Mapping Annotation Example in Hibernate/JPA using Spring Boot and Oracle.
- One To One Bidirectional Mapping Example In Hibernate/JPA Using Spring Boot and Oracle.
- One To Many Mapping Annotation Example In Hibernate/JPA Using Spring Boot And Oracle.
- Many To One Unidirectional Mapping In Hibernate/JPA Annotation Example Using Spring Boot and Oracle.
- One To Many Bidirectional Mapping In Hibernate/JPA Annotation Example Using Spring Boot and Oracle.
- Many To Many Mapping Annotation Example In Hibernate/JPA Using Spring Boot.
See EntityManager docs here.
Hibernate Session docs.
Sumary – We have seen how to get Session from EntityManager to access Hibernate APIs from JPA.