Spring 4 MVC + Hibernate 5 integration example

Spring 4 MVC + Hibernate 5 integration example

In this section, we will learn how to create a web application using Spring MVC and Hibernate ORM framework without any xml configuration.

To integrate Hibernate with Spring MVC application, you can use the LocalSessionFactoryBean class, which set up a shared SessionFactory object within a Spring application context. This SessionFactory object can be passed to DAO classes via dependencies injection.

Tools and technologies used for this example are -

  • Spring 4.3.7.RELEASE
  • Hibernate Validator 5.4.1.Final
  • Hibernate ORM 5.2.10.Final
  • C3P0 0.9.5.2
  • JavaSE 1.8
  • Eclipse Neon.3
  • Maven 3.3.9
  • MySQL Server 5.7.12
  • Apache Tomcat 7.0.47 (Embedded)

 

Project structure

Review the following web project structure build using Maven.

Spring 4 MVC + Hibernate 5 integration example | BORAJI.COM

Refer this article to learn - How to create a web project using maven build tool in eclipse IDE.

 

Jar dependencies

In pom.xml file of your maven project, add the dependencies below.

<dependencies>
<!-- Spring MVC Dependency -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>4.3.7.RELEASE</version>
</dependency>

<!-- Spring ORM -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-orm</artifactId>
  <version>4.3.7.RELEASE</version>
</dependency>

<!-- Mysql Connector -->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>6.0.6</version>
</dependency>

<!-- Hibernate ORM -->
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core</artifactId>
  <version>5.2.10.Final</version>
</dependency>

<!-- Hibernate-C3P0 Integration -->
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-c3p0</artifactId>
  <version>5.2.10.Final</version>
</dependency>

<!-- c3p0 -->
<dependency>
  <groupId>com.mchange</groupId>
  <artifactId>c3p0</artifactId>
  <version>0.9.5.2</version>
</dependency>

<!-- Hibernate Validator -->
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-validator</artifactId>
  <version>5.4.1.Final</version>
</dependency>

<!-- JSTL Dependency -->
<dependency>
  <groupId>javax.servlet.jsp.jstl</groupId>
  <artifactId>javax.servlet.jsp.jstl-api</artifactId>
  <version>1.2.1</version>
</dependency>
<dependency>
  <groupId>taglibs</groupId>
  <artifactId>standard</artifactId>
  <version>1.1.2</version>
</dependency>

<!-- Servlet Dependency -->
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>3.1.0</version>
  <scope>provided</scope>
</dependency>

<!-- JSP Dependency -->
<dependency>
  <groupId>javax.servlet.jsp</groupId>
  <artifactId>javax.servlet.jsp-api</artifactId>
  <version>2.3.1</version>
  <scope>provided</scope>
</dependency>
</dependencies>

 

Model or Entity class

Create a @Entity class, whose field names are annotated with Hibernate Validator constraint and JPA annotations.

We will use this entity class for mapping the database table with User. It will also be used for binding from data to the model using @ModelAttribute annotation in controller's handler method.

User.java

package com.boraji.tutorial.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;

@Entity
@Table(name = "USER_TBL")
public class User {

   @Id
   @GeneratedValue
   @Column(name = "UID")
   private Long id;

   @Column(name = "NAME")
   @Size(max = 20, min = 3, message = "{user.name.invalid}")
   private String name;

   @Column(name = "EMAIL", unique = true)
   @Email(message = "{user.email.invalid}")
   private String email;

   //Getter and Setter methods
   //...
}

In this example, we are using the Hibernate Validator constraints annotations for validation of User form.

To override the default error messages, provided by Hibernate Validator framework, create a messages.properties file under src/main/resources folder.

messages.properties

user.name.invalid = Name entered is invalid. It must be between {2} and {1} characters.
user.email.invalid = Invalid email! Please enter valid email.

 

Controller class

Create a controller class to handle the user form data as follows.

UserController.java

package com.boraji.tutorial.spring.controller;

import java.util.Locale;

import javax.validation.Valid;

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.boraji.tutorial.spring.model.User;
import com.boraji.tutorial.spring.service.UserService;

/**
 * @author imssbora
 */
@Controller
public class UserController {

   @Autowired
   private UserService userService;

   @GetMapping("/")
   public String userForm(Locale locale, Model model) {

      model.addAttribute("user", new User());
      model.addAttribute("users", userService.list());

      return "userForm";
   }

   @PostMapping("/saveUser")
   public String saveUser(@ModelAttribute("user") @Valid User user,
         BindingResult result, Model model) {

      if (result.hasErrors()) {
         
         model.addAttribute("users", userService.list());
         return "userForm";
      }

      userService.save(user);

      return "redirect:/";
   }
}

 

JSP View

Create userForm.jsp file under src\main\webapp\WEB-INF\views folder to take input and display the user details. 

userForm.jsp

<%@ page language="java" contentType="text/html; 
charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<[email protected] uri="http://www.springframework.org/tags/form" prefix="form"%>
<[email protected] 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>BORAJI.COM</title>
<style type="text/css">
fieldset {
	border: 1px solid #dedede;
}

legend {
	font-size: 20px;
	text-transform: uppercase;
}

.error {
	color: red;
}

.resltTable {
	width: 50%;
	border-collapse: collapse;
	border-spacing: 0px;
}

.resltTable td, .resltTable th {
	border: 1px solid #565454;
}
</style>
</head>
<body>
  <fieldset>
    <legend>User Input From</legend>
    <form:form action="saveUser" method="post" modelAttribute="user">
      <table>
        <tr>
          <th>Name</th>
          <td>
            <form:input path="name" /> 
            <form:errors path="name" cssClass="error" />
          </td>
          <th>Email</th>
          <td>
            <form:input path="email" /> 
            <form:errors path="email" cssClass="error" />
          </td>
          <td><button type="submit">Submit</button></td>
        </tr>
      </table>
    </form:form>
  </fieldset>
  <br>
  <br>

  <fieldset>
    <legend>Users List</legend>
    <table class="resltTable">
      <tr>
        <th>Name</th>
        <th>Email</th>
      </tr>
      <c:forEach items="${users}" var="user">
        <tr>
          <td>${user.name}</td>
          <td>${user.email}</td>
        </tr>
      </c:forEach>

    </table>
  </fieldset>

</body>
</html>

The <form:errors> is used to display the error messages and the path attribute indicate the field name of model class for which the error message should be displayed.

 

Spring configuration

Create a web @Configuration class annotated with @EnableWebMvc and @ComponentScan as follows.

We will override the getValidator() method of WebMvcConfigurerAdapter to set the custom error messages for User form.

WebConfig.java

package com.boraji.tutorial.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.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

/**
 * @author imssbora
 */

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.boraji.tutorial.spring.controller",
      "com.boraji.tutorial.spring.validator" })
public class WebConfig extends WebMvcConfigurerAdapter {

   @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;
   }

}

Create another @Configuration class to configure Hibernate in Spring MVC application.

Annotate this class with @EnableTransactionManagement annotation to enable the transaction management.

AppConfig.java

package com.boraji.tutorial.spring.config;

import java.util.Properties;

import org.springframework.beans.factory.annotation.Autowired;
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.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import static org.hibernate.cfg.Environment.*;
import com.boraji.tutorial.spring.model.User;

/**
 * @author imssbora
 */
@Configuration
@PropertySource("classpath:db.properties")
@EnableTransactionManagement
@ComponentScans(value = { @ComponentScan("com.boraji.tutorial.spring.dao"),
      @ComponentScan("com.boraji.tutorial.spring.service") })
public class AppConfig {

   @Autowired
   private Environment env;

   @Bean
   public LocalSessionFactoryBean getSessionFactory() {
      LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();

      Properties props = new Properties();
      // Setting JDBC properties
      props.put(DRIVER, env.getProperty("mysql.driver"));
      props.put(URL, env.getProperty("mysql.url"));
      props.put(USER, env.getProperty("mysql.user"));
      props.put(PASS, env.getProperty("mysql.password"));

      // Setting Hibernate properties
      props.put(SHOW_SQL, env.getProperty("hibernate.show_sql"));
      props.put(HBM2DDL_AUTO, env.getProperty("hibernate.hbm2ddl.auto"));

      // Setting C3P0 properties
      props.put(C3P0_MIN_SIZE, 
            env.getProperty("hibernate.c3p0.min_size"));
      props.put(C3P0_MAX_SIZE, 
            env.getProperty("hibernate.c3p0.max_size"));
      props.put(C3P0_ACQUIRE_INCREMENT,
            env.getProperty("hibernate.c3p0.acquire_increment"));
      props.put(C3P0_TIMEOUT, 
            env.getProperty("hibernate.c3p0.timeout"));
      props.put(C3P0_MAX_STATEMENTS, 
            env.getProperty("hibernate.c3p0.max_statements"));

      factoryBean.setHibernateProperties(props);
      factoryBean.setAnnotatedClasses(User.class);
      return factoryBean;
   }

   @Bean
   public HibernateTransactionManager getTransactionManager() {
      HibernateTransactionManager transactionManager = new HibernateTransactionManager();
      transactionManager.setSessionFactory(getSessionFactory().getObject());
      return transactionManager;
   }
}

As you can see, we are using the @PropertySource annotation to read the JDBC, Hibernate and C3P0 properties, so we need to create a db.properties file under src/main/resources folder as follows.

db.properties

# MySQL properties
mysql.driver=com.mysql.cj.jdbc.Driver
mysql.url=jdbc:mysql://localhost:3306/BORAJI
mysql.user=root
mysql.password=admin

# Hibernate properties
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update

#C3P0 properties
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.acquire_increment=1
hibernate.c3p0.timeout=1800
hibernate.c3p0.max_statements=150

 

Servlet container initialization

Create a container initializer class by extending the AbstractAnnotationConfigDispatcherServletInitializer class as follows.

MyWebAppInitializer.java

package com.boraji.tutorial.spring.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

/**
 * @author imssbora
 */
public class MyWebAppInitializer
      extends AbstractAnnotationConfigDispatcherServletInitializer {

   @Override
   protected Class<?>[] getRootConfigClasses() {
      return new Class[] { AppConfig.class };
   }

   @Override
   protected Class<?>[] getServletConfigClasses() {
      return new Class[] { WebConfig.class };
   }

   @Override
   protected String[] getServletMappings() {
      return new String[] { "/" };
   }
}

The AbstractAnnotationConfigDispatcherServletInitializer class, implements the WebApplicationInitializer, is implemented in Servlet 3.0+ environments in order to configure the ServletContext programmatically.

 

Build + Deploy + Run application

Use the following maven commands to build, deploy and run Tomcat server.

mvn clean install  (This command triggers war packaging)

mvn tomcat7:run (This command run embedded tomcat and deploy war file automatically)

You can refer this link to learn how to run the above commands in Eclipse IDE.


Type the following URLs in browser's address bar to open the user input from.

http://localhost:8080/

Spring 4 MVC + Hibernate 5 integration example | BORAJI.COM

You will see the user details on successful submission of form data as follows.

Spring 4 MVC + Hibernate 5 integration example | BORAJI.COM