In this spring 5 hibernate 5 annotation example tutorial, learn to create Spring 5 MVC web application, handle form submission, integrate hibernate 5 to connect to backend database and adding hibernate validator for input form fields validation.
We will create a simple screen where we can add user fields (name and email). These details will be first validated and then stored in HSQL database using hibernate. The page will list down all stored users as well.
Table of Contents 1. Development Environment 2. Project Structure 3. Maven Dependencies 4. Configure DispatcherServlet 5. Spring WebMVC Configuration 6. Hibernate Configuration 7. Spring Controller and Path Mappings 8. Service and DAO layer 9. View and Messages 10. Demo
1. Development Environment
- Eclipse Neon.2
- JDK 1.8
- Spring 5.2.0.RELEASE
- Hibernate 5.2.11.Final
- Hibernate validator 5.4.1.Final
- Servlets 3.1.0
- HSQLDB 1.8.0.10
- Tomcat 7 maven plugin 2.2
2. Project Structure
This project has typical maven web application structure.

2.1. Class Diagram

3. Maven Dependencies
Find project dependencies used to run this example in pom.xml
file.
<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>com.howtodoinjava.spring5.demo</groupId> <artifactId>spring5-mvc-hibernate-example</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <failOnMissingWebXml>false</failOnMissingWebXml> <spring.version>5.2.0.RELEASE</spring.version> <hibernate.version>5.2.11.Final</hibernate.version> <hibernate.validator>5.4.1.Final</hibernate.validator> <c3p0.version>0.9.5.2</c3p0.version> <jstl.version>1.2.1</jstl.version> <tld.version>1.1.2</tld.version> <servlets.version>3.1.0</servlets.version> <jsp.version>2.3.1</jsp.version> <hsqldb.version>1.8.0.10</hsqldb.version> </properties> <dependencies> <!-- Spring MVC Dependency --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!-- Spring ORM --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <!-- Hibernate Core --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> <!-- Hibernate-C3P0 Integration --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-c3p0</artifactId> <version>${hibernate.version}</version> </dependency> <!-- c3p0 --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>${c3p0.version}</version> </dependency> <!-- Hibernate Validator --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>${hibernate.validator}</version> </dependency> <!-- JSTL Dependency --> <dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>javax.servlet.jsp.jstl-api</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>${tld.version}</version> </dependency> <!-- Servlet Dependency --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlets.version}</version> <scope>provided</scope> </dependency> <!-- JSP Dependency --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>${jsp.version}</version> <scope>provided</scope> </dependency> <!-- HSQL Dependency --> <dependency> <groupId>hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>${hsqldb.version}</version> </dependency> </dependencies> <build> <sourceDirectory>src/main/java</sourceDirectory> <resources> <resource> <directory>src/main/resources</directory> </resource> </resources> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <path>/</path> </configuration> </plugin> </plugins> </build> </project>
4. DispatcherServlet Configuration
With the release of the Servlet 3.0 spec it became possible to configure your Servlet Container with (almost) no xml. For this there is the ServletContainerInitializer
in the Servlet specification. In this class you can register filters, listeners, servlets etc. as you would traditionally do in a web.xml
.
Spring provides SpringServletContainerInitializer
which knows how to handle WebApplicationInitializer
classes. AbstractAnnotationConfigDispatcherServletInitializer
class implements WebMvcConfigurer
which internally implements WebApplicationInitializer
. It registers a ContextLoaderlistener
(optionally) and a DispatcherServlet
and allows you to easily add configuration classes to load for both classes and to apply filters to the DispatcherServlet and to provide the servlet mapping.
package com.howtodoinjava.demo.spring.config; public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[] { HibernateConfig.class }; } @Override protected Class<?>[] getServletConfigClasses() { return new Class[] { WebMvcConfig.class }; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } }
5. Spring WebMVC Configuration
Spring MVC configuration using annotation configuration is given below.
package com.howtodoinjava.demo.spring.config; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.validation.Validator; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView; @Configuration @EnableWebMvc @ComponentScan(basePackages = { "com.howtodoinjava.demo.spring"}) public class WebMvcConfig implements WebMvcConfigurer { @Bean public InternalResourceViewResolver resolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setViewClass(JstlView.class); resolver.setPrefix("/WEB-INF/views/"); resolver.setSuffix(".jsp"); return resolver; } @Bean public MessageSource messageSource() { ResourceBundleMessageSource source = new ResourceBundleMessageSource(); source.setBasename("messages"); return source; } @Override public Validator getValidator() { LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean(); validator.setValidationMessageSource(messageSource()); return validator; } }
WebMvcConfigurer
defines options for customizing or adding to the default Spring MVC configuration enabled through the use of@EnableWebMvc
.@EnableWebMvc
enables default Spring MVC configuration and registers Spring MVC infrastructure components expected by theDispatcherServlet
.@Configuration
indicates that a class declares one or more@Bean
methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime.@ComponentScan
annotation is used to specify the base packages to scan. Any class which is annotated with @Component and @Configuration will be scanned.InternalResourceViewResolver
helps in mapping the logical view names to directly view files under a certain pre-configured directory.ResourceBundleMessageSource
accesses resource bundles using specified basenames (here it is messages).LocalValidatorFactoryBean
bootstraps ajavax.validation.ValidationFactory
and exposes it through the SpringValidator
interface as well as through the JSR-303Validator
interface and theValidatorFactory
interface itself.
6. Hibernate Configuration
Hibernate configuration used in the example is based on hibernate Java based configuration.
package com.howtodoinjava.demo.spring.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScans; import org.springframework.context.annotation.Configuration; import org.springframework.orm.hibernate5.HibernateTransactionManager; import org.springframework.orm.hibernate5.LocalSessionFactoryBean; import org.springframework.transaction.annotation.EnableTransactionManagement; import com.howtodoinjava.demo.spring.model.User; @Configuration @EnableTransactionManagement public class HibernateConfig { @Autowired private ApplicationContext context; @Bean public LocalSessionFactoryBean getSessionFactory() { LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean(); factoryBean.setConfigLocation(context.getResource("classpath:hibernate.cfg.xml")); factoryBean.setAnnotatedClasses(User.class); return factoryBean; } @Bean public HibernateTransactionManager getTransactionManager() { HibernateTransactionManager transactionManager = new HibernateTransactionManager(); transactionManager.setSessionFactory(getSessionFactory().getObject()); return transactionManager; } }
LocalSessionFactoryBean
creates a HibernateSessionFactory
. This is the usual way to set up a shared Hibernate SessionFactory in a Spring application context.EnableTransactionManagement
enables Spring’s annotation-driven transaction management capability.HibernateTransactionManager
binds a Hibernate Session from the specified factory to the thread, potentially allowing for one thread-bound Session per factory. This transaction manager is appropriate for applications that use a single HibernateSessionFactory
for transactional data access, but it also supports directDataSource
access within a transaction i.e. plain JDBC.
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.archive.autodetection">class,hbm</property> <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property> <property name="hibernate.show_sql">true</property> <property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property> <property name="hibernate.connection.username">sa</property> <property name="hibernate.connection.password"></property> <property name="hibernate.connection.url">jdbc:hsqldb:mem:howtodoinjava</property> <property name="hibernate.hbm2ddl.auto">create</property> <property name="hibernate.c3p0.min_size">5</property> <property name="hibernate.c3p0.max_size">20</property> <property name="hibernate.c3p0.acquire_increment">2</property> <property name="hibernate.c3p0.acquire_increment">1800</property> <property name="hibernate.c3p0.max_statements">150</property> </session-factory> </hibernate-configuration>
7. Spring Controller and REST Mappings
Controller class has two simple REST mappings for GET
and POST
operations. If input fields are not validated, then return the same form bean to display error messages. Else return refreshed view.
package com.howtodoinjava.demo.spring.controller; import java.util.Locale; import javax.validation.alid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import com.howtodoinjava.demo.spring.model.User; import com.howtodoinjava.demo.spring.service.UserService; @Controller public class UserController { @Autowired private UserService userService; @GetMapping("/") public String userForm(Locale locale, Model model) { model.addAttribute("users", userService.list()); return "editUsers"; } @ModelAttribute("user") public User formBackingObject() { return new User(); } @PostMapping("/addUser") public String saveUser(@ModelAttribute("user") @Valid User user, BindingResult result, Model model) { if (result.hasErrors()) { model.addAttribute("users", userService.list()); return "editUsers"; } userService.save(user); return "redirect:/"; } }
8. Service and DAO layer
Service and DAO layer are normal service components annotated with @Service
and @Repository
annotations. @Transactional
annotation is applied at service layer for transaction support.
Read More: @Service and @Repository Anootations
public interface UserService { void save(User user); List<User> list(); } @Service public class UserServiceImp implements UserService { @Autowired private UserDao userDao; @Transactional public void save(User user) { userDao.save(user); } @Transactional(readOnly = true) public List<User> list() { return userDao.list(); } }
public interface UserDao { void save(User user); List<User> list(); } @Repository public class UserDaoImp implements UserDao { @Autowired private SessionFactory sessionFactory; @Override public void save(User user) { sessionFactory.getCurrentSession().save(user); } @Override public List<User> list() { @SuppressWarnings("unchecked") TypedQuery<User> query = sessionFactory.getCurrentSession().createQuery("from User"); return query.getResultList(); } }
package com.howtodoinjava.demo.spring.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import javax.validation.constraints.Size; import org.hibernate.validator.constraints.Email; import org.hibernate.validator.constraints.NotEmpty; @Entity @Table(name = "TBL_USERS") public class User { @Id @GeneratedValue @Column(name = "USER_ID") private Long id; @Column(name = "USER_NAME") @Size(max = 20, min = 3, message = "{user.name.invalid}") @NotEmpty(message="Please Enter your name") private String name; @Column(name = "USER_EMAIL", unique = true) @Email(message = "{user.email.invalid}") @NotEmpty(message="Please Enter your email") private String email; 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 getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
9. View and Message Resource
Finally, JSP file used and messages resource bundle used.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Spring5 MVC Hibernate Demo</title> <style type="text/css"> .error { color: red; } table { width: 50%; border-collapse: collapse; border-spacing: 0px; } table td { border: 1px solid #565454; padding: 20px; } </style> </head> <body> <h1>Input Form</h1> <form:form action="addUser" method="post" modelAttribute="user"> <table> <tr> <td>Name</td> <td> <form:input path="name" /> <br /> <form:errors path="name" cssClass="error" /> </td> </tr> <tr> <td>Email</td> <td> <form:input path="email" /> <br /> <form:errors path="email" cssClass="error" /> </td> </tr> <tr> <td colspan="2"><button type="submit">Submit</button></td> </tr> </table> </form:form> <h2>Users List</h2> <table> <tr> <td><strong>Name</strong></td> <td><strong>Email</strong></td> </tr> <c:forEach items="${users}" var="user"> <tr> <td>${user.name}</td> <td>${user.email}</td> </tr> </c:forEach> </table> </body> </html>
10. Demo
Let’s run the application using maven tomcat7 plugin. Execute maven goal : tomcat7:run
.
URL: http://localhost:8080



Check Server logs.
Hibernate: call next value for hibernate_sequence Hibernate: insert into TBL_USERS (USER_EMAIL, USER_NAME, USER_ID) values (?, ?, ?) Hibernate: select user0_.USER_ID as USER_ID1_0_, user0_.USER_EMAIL as USER_EMA2_0_, user0_.USER_NAME as USER_NAM3_0_ from TBL_USERS user0_
I hope that you have find this spring hibernate web application example to set you start for developing your own application. This is primarily for beginners, yet it will help you build any Spring MVC with hibernate integration example with annotations.
Happy Learning !!
Hi Lokesh ,
Plz provide war file mention project and as well as project in their respective page
Must be
Thanks for giving proper solution.
Hi,
I am getting a build error related to SessionFactory. I looked on web for a solution to no avail. Error: “The type org.hibernate.Session cannot be resolved. It is indirectly referenced from required .class files” UserDaoImp.java
/spring5-mvc-hibernate-example/src/main/java/com/howtodoinjava/demo/spring/dao line 29 Java Problem
This is the offending line of code:
[sessionFactory.getCurrentSession().save(user);]
I am importing import org.hibernate.SessionFactory;
Mave update does not help.
Is there a descrepancy with Spring 5.0.2 and and Hibernate?
spring.version>5.0.2.RELEASE5.2.11.Final</hibernate.version
thanks
rrsqrd
Please change Spring version from 5.0.0.RELEASE to 5.0.2.RELEASE for working.
Deploying on GlassFish Server 4.1.1
profile mode: false
debug mode: false
force redeploy: true
In-place deployment at E:\Java Projects\SpringMCVConfigWithAnnotationDemo\target\SpringMCVConfigWithAnnotationDemo-1.0
GlassFish Server 4.1.1, deploy, null, fals
I am getting about error…pls guide me
Error : Exception while loading the app : java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘getSessionFactory’ defined in test.config.HibernateConfig: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError
Error
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘userServiceImp’: Unsatisfied dependency expressed through field ‘userDao’; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type ‘com.howtodoinjava.demo.spring.dao.UserDao’ available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
i am also getting the same error.
write @Repository Annotation on top of the Dao Impl class
You want to drop the whole line starting with “@ComponentScans […]” in “HibernateConfig.java” otherwise all the component beans (e.g. the UserController) get instantiated twice.
As this is one of the very few up-to-date “Spring sans Spring-Boot” examples on the internet, I’d like to say thanks!
Thanks for scanning with sharp eyes and reporting this. I will update it.
Hi Gupta!
any news about your update?
thanks!
What update?