Introduction
Java Persistence API (JPA) is a specification and Hibernate is one of the popular implementations of JPA. Hibernate provides some additional features that are not supported by JPA.
For example, Hibernate’s org.hibernate.query.Query
interface provides a stream()
method to retrieve a stream over the query results. This method uses ScrollableResultSet
to scroll through the result set and fetch them in small batches instead of fetching all the records at once.
In order to make use of such Hibernate specific features, we are going to configure Hibernate 5 with Spring using MySQL database and create a repository to fetch stream of users using the stream()
function.
Let’s Get Started
Add Dependencies
We are going to add spring-orm
, hibernate-core
and tomcat-dpcp
dependencies in our existing spring application to integrate Hibernate.
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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.javachinna</groupId>
<artifactId>SpringHibernateDemo</artifactId>
<packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Spring 5 Hibernate 5 Integration</name>
<url>http://maven.apache.org</url>
<properties>
<java-version>11</java-version>
<spring.version>5.2.3.RELEASE</spring.version>
<hibernate.version>5.4.1.Final</hibernate.version>
<tomcat.version>9.0.37</tomcat.version>
<slf4j.version>1.7.25</slf4j.version>
<lombok.version>1.18.12</lombok.version>
<junit.jupiter.version>5.7.0</junit.jupiter.version>
<junit.platform.version>1.7.0</junit.platform.version>
</properties>
<dependencies>
<!-- Spring Web MVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Servlet API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!-- Logback dependencies -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- Spring ORM, hibernate libraries -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!-- Tomcat Database Connection Pooling package -->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-dbcp</artifactId>
<version>${tomcat.version}</version>
</dependency>
<!-- MySQL Connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<!-- Spring test and JUnit 5 libraries -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>${junit.platform.version}</version>
</dependency>
</dependencies>
<build>
<finalName>SpringHibernate</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${java-version}</source>
<target>${java-version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.3</version>
<configuration>
<warSourceDirectory>src/main/webapp</warSourceDirectory>
<warName>SpringHibernate</warName>
</configuration>
</plugin>
</plugins>
</build>
</project>
Configure Hibernate
HibernateConf.java
This class is responsible for configuring DataSource
, SessionFatory
and HibernateTransactionManager
@EnableTransactionManagement
enables Spring’s annotation-driven transaction management capability. It should be used on @Configuration
classes
package com.javachinna.config;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
public class HibernateConf {
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan("com.javachinna.model");
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/demo?createDatabaseIfNotExist=true");
dataSource.setUsername("root");
dataSource.setPassword("secret");
return dataSource;
}
@Bean
public PlatformTransactionManager hibernateTransactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
private final Properties hibernateProperties() {
Properties hibernateProperties = new Properties();
// hibernateProperties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
return hibernateProperties;
}
}
Create Repository
Now we will be able to inject the raw Hibernate SessionFactory
with @Autowired
annotation in the Repository
class as follows
package com.javachinna.repo;
import java.util.stream.Stream;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.javachinna.model.User;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Repository
@Transactional
public class UserRepository {
@Autowired
private SessionFactory sessionFactory;
public Stream<User> getUers() {
Session session = null;
Transaction transaction = null;
Stream<User> users = null;
try {
session = sessionFactory.openSession();
transaction = session.beginTransaction();
users = session.createQuery("select u from User u", User.class).stream();
transaction.commit();
} catch (Exception e) {
log.error("Exception occurred", e);
if (transaction != null) {
transaction.rollback();
}
} finally {
session.close();
}
return users;
}
}
After processing the Stream<Users>
returned by the UserRepository
, we should call Stream#close()
method to deallocate the underlying resource right away.
users.map(u -> u.getDisplayName()).forEach(n -> log.info(n));
users.close();
Source Code
https://github.com/JavaChinna/spring-hibernate-integration
References
https://www.baeldung.com/hibernate-5-spring
Conclusion
That’s all folks. In this article, we have bootstrapped Hibernate 5 with Spring without JPA.
Please share the article with your friends if you like it. Thank you for reading.
Read Next: Call Stored Procedure and Map the Native Query Result to POJO with Hibernate