Spring mvc and Hibernate tutorial without xml configuration

Spring Mvc And Hibernate Tutorial Without Xml Configuration

In this tutorial, we will learn how to create a web application using Spring MVC and Hibernate ORM framework without xml configuration. To integrate Hibernate with Spring MVC application. We 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.

We will use in this tutorial these technologies and tools:

  • 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

Project structure

This is the web project structure build using Maven.

Spring mvc and Hibernate tutorial without xml configuration

Maven dependencies:

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

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.elgarnaoui</groupId>
	<artifactId>tutorial</artifactId>
	<name>SpringTuto</name>
	<version>1.0.0-BUILD-SNAPSHOT</version>
	<packaging>war</packaging>
	<properties>
		<java-version>1.8</java-version>
		<failOnMissingWebXml>false</failOnMissingWebXml>
	</properties>

	<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>

	<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>

			<!-- Embedded Apache Tomcat required for testing war -->
			<plugin>
				<groupId>org.apache.tomcat.maven</groupId>
				<artifactId>tomcat7-maven-plugin</artifactId>
				<version>2.2</version>
				<configuration>
					<path>/</path>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Spring configuration:

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

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

WebConfig.java

package com.elgarnaoui.tutorial;

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 elgarnaoui.com
 */

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.elgarnaoui"})
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.

Then, annotate this class with @EnableTransactionManagement annotation to enable the transaction management.

AppConfig.java

package com.elgarnaoui.tutorial;

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 com.elgarnaoui.tutorial.model.User;

import static org.hibernate.cfg.Environment.*;

/**
 * @author elgarnaoui.com
 */
@Configuration
@PropertySource("classpath:database.properties")
@EnableTransactionManagement
@ComponentScans(value = @ComponentScan("com.elgarnaoui"))
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"));

      //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 database.properties file under src/main/resources folder as follows.

database.properties

# MySQL properties
mysql.driver=com.mysql.cj.jdbc.Driver
mysql.url=jdbc:mysql://localhost:3306/elgarnaoui
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.elgarnaoui.tutorial;

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

/**
 * @author elgarnaoui.com
 */
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.

Entities class:

Create a @Entity class, Then we will annotate those fields names with Hibernate Validator constraint and JPA annotations.

Also, we will use this entity class for mapping the database table with User. And we will use it for binding from data to the model using @ModelAttribute annotation in controller’s handler method.

User.java

package com.elgarnaoui.tutorial.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")
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;

	public User() {
		super();
		// TODO Auto-generated constructor stub
	}

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

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 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.

Data Access Object (DAO) class

Create @Repository classes under com.elgarnaoui.tutorial.dao package as follows.

UserDao.java

package com.elgarnaoui.tutorial.dao;

import java.util.List;

import com.elgarnaoui.tutorial.model.User;

public interface UserDao {

	void save(User user);
	List<User> list();
}

UserDaoImpl.java

package com.elgarnaoui.tutorial.dao;

import java.util.List;

import javax.persistence.TypedQuery;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.elgarnaoui.tutorial.model.User;


@Repository
public class UserDaoImpl 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();
   }
}

Service class

Create @Service classes under com.elgarnaoui.tutorial.service package as follows.

UserService.java

package com.elgarnaoui.tutorial.service;

import java.util.List;

import com.elgarnaoui.tutorial.model.User;

public interface UserService {

	void save(User user);

	List<User> list();
}

UserServiceImpl.java

package com.elgarnaoui.tutorial.service;

import java.util.List;

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

import com.elgarnaoui.tutorial.dao.UserDao;
import com.elgarnaoui.tutorial.model.User;

@Service
public class UserServiceImpl 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();
   }

}

Controller class:

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

UserController.java

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

/**
 * @author elgarnaoui.com
 */
@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 "user/";
	}

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

		if (result.hasErrors()) {

			model.addAttribute("users", userService.list());
			return "user/";
		}

		userService.save(user);

		return "redirect://";
	}
}

JSP View

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

user.jsp

<%@ 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>ELGARNAOUI.COM</title>
<style type="text/css">
fieldset {
	border: 1px solid #dedede;
}

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

.error {
	color: red;
}

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

.resltTable td, .resltTable th {
	border: 1px solid #565454;
}
</style>
</head>
<body>
	<fieldset style="width: 40%">
		<legend>User 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>
				</tr>
				<tr>
					<th>Email :</th>
					<td><form:input path="email" /> <form:errors path="email"
							cssClass="error" /></td>
				</tr>
				<tr>
					<td colspan="2"><button type="submit">Submit</button></td>
				</tr>
				
			</table>
		</form:form>
	</fieldset>
	<br>
	<br>

	<fieldset style="width: 40%">
		<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 show the field name of model class for which display the error message.

Build + Deploy + Run application:

Use this 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)

open the browser and type this URLs in the browser’s address bar to open the user input from.

http://localhost:8080/tutorial/

Spring mvc and Hibernate tutorial without xml configuration

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

Spring mvc and Hibernate tutorial without xml configuration

Make contact with us if you have any requests or issues. To support us share this post with your friends on social media below đŸ™‚

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *