About Spring MVC

Spring MVC (Model, View Controller) framework is the most popular Java web framework used for developing loosely coupled web application. It has various ready made components and supports concepts like Dependency Injection which makes it more powerful and easy to use.

To learn more about Spring MVC, please follow the link:

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html

About Hibernate

Hibernate is a Java ORM (Object Relational Mapping) framework that maps Java classes to database tables and Java types to SQL data types. By using Hibernate, we are free from writing SQL queries in our Java code.

To learn more about Hibernate, pleae follow the link:

https://docs.oracle.com/cd/E13224_01/wlw/docs103/guide/ormworkbench/hibernate-tutorial/tutHibernate1.html

Basic CRUD (Create, Read, Update, Delete)

Let us create a basic CRUD example with Spring MVC, MySQL and Hibernate using annotation based configuration instead of XML.

Here are the steps:

  1. Make sure MySQL is installed on the system
  2. Start Spring Source Tool Suite and create a Maven based project. File -> New Project -> Maven Project -> maven-archetype-webapp
  3. Enter following information:
     Group Id: test
     Artifact Id: spring_crud
     Package: com.spring.crud
  4. If you don’t see the folder src/main/java, create a new folder named java under src/main. Then right click on project -> Maven -> Update project
  5. Update your pom.xml with following data:
    <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>test</groupId>
      <artifactId>spring_crud</artifactId>
      <packaging>war</packaging>
      <version>0.0.1-SNAPSHOT</version>
      <name>spring_crud Maven Webapp</name>
      <url>http://maven.apache.org</url>
    
      <properties>
         <spring.version>4.2.0.RELEASE</spring.version>
         <hibernate.version>4.3.11.Final</hibernate.version>
    
         <mysql.version>5.1.24</mysql.version>
    
         <slf4j.version>1.6.1</slf4j.version>
         <log4j.version>1.2.14</log4j.version>
      </properties>
    
      <dependencies>
    
        <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>3.8.1</version>
           <scope>test</scope>
        </dependency>
    
        <!-- servlet dependencies -->
    
        <dependency>
           <groupId>jstl</groupId>
           <artifactId>jstl</artifactId>
           <version>1.2</version>
        </dependency>
    
        <dependency>
           <groupId>javax.servlet</groupId>
           <artifactId>javax.servlet-api</artifactId>
           <version>3.1.0</version>
           <scope>provided</scope>
         </dependency>
    
         <dependency>
           <groupId>javax.servlet.jsp</groupId>
           <artifactId>javax.servlet.jsp-api</artifactId>
           <version>2.3.1</version>
           <scope>provided</scope>
         </dependency>
         <dependency>
           <groupId>commons-dbcp</groupId>
           <artifactId>commons-dbcp</artifactId>
           <version>1.4</version>
           <type>jar</type>
           <scope>runtime</scope>
         </dependency>
    
         <dependency>
           <groupId>commons-io</groupId>
           <artifactId>commons-io</artifactId>
           <version>1.3.2</version>
         </dependency>
    
         <dependency>
           <groupId>commons-collections</groupId>
           <artifactId>commons-collections</artifactId>
           <version>3.2.1</version>
         </dependency>
    
         <!-- spring dependencies -->
    
         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
         </dependency>
    
         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring.version}</version>
            <type>jar</type>
            <scope>compile</scope>
         </dependency>
    
         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
            <type>jar</type>
            <scope>compile</scope>
         </dependency>
    
         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
            <type>jar</type>
            <scope>compile</scope>
         </dependency>
    
         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
            <type>jar</type>
            <scope>compile</scope>
         </dependency>
    
         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
            <type>jar</type>
            <scope>compile</scope>
         </dependency>
    
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-orm</artifactId>
             <version>${spring.version}</version>
            <type>jar</type>
            <scope>compile</scope>
         </dependency>
    
         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
            <type>jar</type>
            <scope>compile</scope>
         </dependency>
    
         <!-- hibernate and mysql dependencies -->
    
         <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
            <type>jar</type>
            <scope>compile</scope>
         </dependency>
    
         <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>1.0</version>
            <type>jar</type>
            <scope>compile</scope>
         </dependency>
     
         <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
            <scope>runtime</scope>
         </dependency>
    
         <!-- slf4j dependencies -->
     
         <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
            <type>jar</type>
            <scope>compile</scope>
         </dependency>
    
         <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
            <type>jar</type>
            <scope>compile</scope>
         </dependency>
    
         <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${slf4j.version}</version>
            <type>jar</type>
            <scope>compile</scope>
         </dependency>
    
       </dependencies>
    
       <build>
          <finalName>spring_crud</finalName>
       </build>
    </project>
  6. Now create a new package: com.spring.crud.config. Then create following classes in it:

    WebConfig.java
    For web application settings.

    package com.spring.crud.config;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
    @Configuration
    @EnableWebMvc
    public class WebConfig extends WebMvcConfigurerAdapter {
    
       @Override
       public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
          configurer.enable();
       }
    }

    SpringMvcInitializer.java
    For initializing spring settings

    package com.spring.crud.config;
    
    import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
    
    public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    
        @Override
        protected Class<?>[] getRootConfigClasses() {
            return new Class[] { AppConfig.class };
        }
    
        @Override
        protected Class<?>[] getServletConfigClasses() {
           return null;
        }
    
        @Override
        protected String[] getServletMappings() {
           return new String[] { "/" };
        }
    }
    

    PersistenceConfig.java
    For initializing hibernate settings

    package com.spring.crud.config;
    
    import java.util.Properties;
    import javax.sql.DataSource;
    
    import org.apache.commons.dbcp.BasicDataSource;
    import org.hibernate.SessionFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.PropertySource;
    import org.springframework.core.env.Environment;
    import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
    import org.springframework.orm.hibernate4.HibernateTransactionManager;
    import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    @Configuration
    @EnableTransactionManagement
    @PropertySource({ "classpath:persistence-mysql.properties" })
    public class PersistenceConfig {
    
        @Autowired
        private Environment env;
    
        @Bean
        public LocalSessionFactoryBean sessionFactory() {
           LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
           sessionFactory.setDataSource(restDataSource());
           sessionFactory.setPackagesToScan(new String[] { "com.spring.crud.entity" });
           sessionFactory.setHibernateProperties(hibernateProperties());
    
           return sessionFactory;
        }
    
        @Bean
        public DataSource restDataSource() {
           BasicDataSource dataSource = new BasicDataSource();
           dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
           dataSource.setUrl(env.getProperty("jdbc.url"));
           dataSource.setUsername(env.getProperty("jdbc.user"));
           dataSource.setPassword(env.getProperty("jdbc.pass"));
    
           return dataSource;
        }
    
        @Bean
        @Autowired
        public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
            HibernateTransactionManager txManager = new HibernateTransactionManager();
            txManager.setSessionFactory(sessionFactory);
    
            return txManager;
        }
    
        @Bean
        public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
            return new PersistenceExceptionTranslationPostProcessor();
        }
    
        Properties hibernateProperties() {
           return new Properties() {
              private static final long serialVersionUID = -1578822918347057946L;
              { 
                  setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
                  setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
                  setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
              }
           };
        }
    }

    AppConfig.java
    For loading application configurations.

    package com.spring.crud.config;
    
    import javax.servlet.ServletContext;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Import;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.view.InternalResourceViewResolver;
    import org.springframework.web.servlet.view.JstlView;
    
    @EnableWebMvc
    @Configuration
    @ComponentScan({ "com.spring.crud.*" })
    @Import({ WebConfig.class, PersistenceConfig.class })
    public class AppConfig {
    
         @Autowired
         ServletContext servletContext;
     
         @Bean
         public InternalResourceViewResolver viewResolver() {
             InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
             viewResolver.setViewClass(JstlView.class);
             viewResolver.setPrefix("/WEB-INF/views/");
             viewResolver.setSuffix(".jsp");
            
             return viewResolver;
        }
    }
  7. Create a new file named persistence-mysql.properties in src/main/resources folder. This file will contain our database information.
    jdbc.driverClassName=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/spring_db?createDatabaseIfNotExist=true
    jdbc.user=spring
    jdbc.pass=hibernate
    hibernate.hbm2ddl.auto=create
    hibernate.show_sql=false
    hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
  8. After lot of configuration, next we will create our entity class for managing employees. Create a new package named com.spring.crud.entity and create Employee.java in it with following code:
    package com.spring.crud.entity;
    
    import java.util.Date;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Table;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import org.springframework.format.annotation.DateTimeFormat;
    
    @Entity
    @Table(name="employees")
    public class Employee {
    
        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        private Integer id;
     
        @Column(name="name", length=255)
        private String name;
     
        @Column(name="gender", length=10)
        private String gender;
     
        @DateTimeFormat(pattern="mm/dd/yyyy")
        @Column(name="date_of_birth")
        private Date dateOfBirth;
    
        public Integer getId() {
           return id;
        }
    
        public String getName() {
           return name;
        }
    
        public String getGender() {
           return gender;
        }
    
        public Date getDateOfBirth() {
           return dateOfBirth;
        }
    
        public void setId(Integer id) {
           this.id = id;
        }
    
        public void setName(String name) {
           this.name = name;
        }
    
        public void setGender(String gender) {
           this.gender = gender;
        }
    
        public void setDateOfBirth(Date dateOfBirth) {
           this.dateOfBirth = dateOfBirth;
        }
    }
  9. Next we will create data access classes. Create a new package named com.spring.crud.dao
    Create the HibernateUtil file that loads Hibernate settings in Spring.HibernateUtil.java

    package com.spring.crud.dao;
    
    import javax.annotation.PostConstruct;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
    
    public class HibernateUtil extends HibernateDaoSupport{
    
        @Autowired
        private SessionFactory sessionFactory;
    
        @PostConstruct
        public void init() {
            setSessionFactory(sessionFactory);
        } 
     
        public Session getCurrentSession() {
            return sessionFactory.getCurrentSession();
        }
    }

    Create interface EmployeeDAO and class EmployeeDAOImpl with following code:

    EmployeeDAO.java

    package com.spring.crud.dao;
    
    import java.util.List;
    import com.spring.crud.entity.Employee;
    
    public interface EmployeeDAO {
          boolean save(Employee employee);
          boolean update(Employee employee);
          Employee find(Integer id);
          List<Employee> getEmployees();
    }
    

    EmployeeDAOImpl.java

    package com.spring.crud.dao;
    
    import java.util.List;
    
    import javax.transaction.Transactional;
    
    import org.hibernate.Query;
    import org.hibernate.Session;
    import org.springframework.stereotype.Repository;
    
    import com.spring.crud.entity.Employee;
    
    @Transactional
    @Repository
    public class EmployeeDAOImpl extends HibernateUtil implements EmployeeDAO{
    
         public boolean save(Employee employee) {
    
              Session session = getCurrentSession();
     
              session.save(employee);
     
              return true;
         }
    
         public boolean update(Employee employee) {
    
              Session session = getCurrentSession();
     
              session.update(employee);
     
              return false;
         }
    
         public Employee find(Integer id) {
    
              Session session = getCurrentSession();
     
              Employee employee = (Employee)session.get(Employee.class, id); 
     
              return employee;
         }
    
         public List<Employee> getEmployees() {
    
              Session session = getCurrentSession();
    
              Query query = session.createQuery("from Employee");
     
              @SuppressWarnings("unchecked")
              List<Employee> employees = (List<Employee>)query.list();
     
              return employees;
         }
    
         public boolean remove(Integer id) {
    
              Session session = getCurrentSession();
     
              Employee employee = (Employee)session.get(Employee.class, id);
    
              if(employee!=null){
     
                  session.delete(employee);
     
                  return true;
              }
     
              return false;
         }
    } 
  10. Now we will create the service layer. Create a new package named com.spring.crud.service. Create the interface EmployeeService and its implementation class EmployeeServiceImpl like this:
    EmployeeService.java

    package com.spring.crud.service;
    
    import java.util.List;
    import com.spring.crud.entity.Employee;
    
    public interface EmployeeService {
    
        boolean save(Employee employee);
     
        boolean update(Employee employee);
     
        Employee find(Integer id);
     
        List<Employee> getEmployees();
    }

    EmployeeServiceImpl.java

    package com.spring.crud.service;
    
    import java.util.List;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import com.spring.crud.dao.EmployeeDAO;
    import com.spring.crud.entity.Employee;
    
    @Service
    public class EmployeeServiceImpl implements EmployeeService {
    
        @Autowired
        private EmployeeDAO dao;
     
        public boolean save(Employee employee) {
    
            return dao.save(employee);
        }
    
        public boolean update(Employee employee) {
    
            return dao.update(employee);
        }
    
        public Employee find(Integer id) {
    
            return dao.find(id);
        }
    
        public List<Employee> getEmployees() {
    
            return dao.getEmployees();
        }
    }
  11. Now we will create controller to handle the requests. Create a new package named com.spring.crud.controller and create the EmployeeController class in it with following code:EmployeeController.java
    package com.spring.crud.controller;
    
    import java.util.Arrays;
    import java.util.List;
    import javax.servlet.http.HttpServletRequest;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.ModelMap;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import com.spring.crud.entity.Employee;
    import com.spring.crud.service.EmployeeService;
    
    @Controller
    public class EmployeeController {
    
        @Autowired
        private EmployeeService service;
     
        @RequestMapping("/")
        public String home(ModelMap map){
     
             List<Employee> employees = service.getEmployees();
     
            if(employees.isEmpty())
                 map.addAttribute("found", false);
            else{
                 map.addAttribute("found", true);
                 map.addAttribute("employees", employees);
            }
     
            return "home";
        }
     
        @RequestMapping("/create-employee")
        public String create(ModelMap map){
    
             List<String> genders = Arrays.asList(new String[]{"Male", "Female"});
     
             map.addAttribute("genders", genders);
     
             map.addAttribute("employee", new Employee());
             return "create";
        }
     
        @RequestMapping("/save-employee")
        public String save(Employee employee){
    
            service.save(employee);
    
            return "redirect:/";
        }
     
        @RequestMapping("/edit-employee/{id}")
        public String edit(@PathVariable Integer id, ModelMap map, HttpServletRequest request){
     
            Employee employee = service.find(id);
     
            if(employee!=null){
     
                // save employee id in session for update
                request.getSession().setAttribute("employee_id", id);
    
                List<String> genders = Arrays.asList(new String[]{"Male", "Female"});
     
                map.addAttribute("genders", genders);
                map.addAttribute("employee", employee);
     
                return "edit";
           }
           else
                return "invalid";
        }
     
        @RequestMapping("/update-employee")
        public String update(Employee employee, HttpServletRequest request){
     
            Object employeeId = request.getSession().getAttribute("employee_id");
     
            if(employeeId != null){
     
                Integer id = Integer.parseInt(employeeId.toString());
     
                employee.setId(id);
     
                service.update(employee);
     
                return "redirect:/";
            }
            else
                return "redirect:/"; // id not found, move to home page
        }
     
        @RequestMapping("/remove-employee/{id}")
        public String remove(@PathVariable Integer id){
    
            Employee employee = service.find(id);
     
            if(employee!=null){
     
               service.remove(id);
     
               return "redirect:/";
           }
           else
               return "invalid";
        }
    }

    Lastly, we create the views. Here are the four view files we will create under webapp/WEB-INF/views folder:

    home.jsp

    <%@ page isELIgnored="false" %>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
    
    <html>
    
    <head>
     <title>Employee List</title>
    </head>
    
    <body>
     
     <a href="create-employee">Create new employee</a>
     
     <hr/>
     
     <c:if test="${found}">
     
     <table style="width: 50%; text-align: left">
    
    <tr>
     <th>Id</th>
     <th>Name</th>
     <th>Gender</th>
     <th>Date of birth</th>
     <th>&nbsp;</th>
     </tr> 
     
     <c:forEach items="${employees}" var="employee">
     <tr>
     <td>${employee.id}</td>
     <td>${employee.name}</td>
     <td>${employee.gender}</td>
     <td><fmt:formatDate value="${employee.dateOfBirth}" pattern="mm-dd-yyyy"/></td>
     <td><a href="edit-employee/${employee.id}">Edit</a> &nbsp; | &nbsp; <a href="remove-employee/${employee.id}">Remove</a></td>
     </tr> 
     </c:forEach>
     
     </table>
    
    </c:if>
     
     <c:if test="${found eq false}">
     No employees added
     </c:if>
    
    </body>
    
    </html>

    create.jsp

    <%@ page isELIgnored="false" %>
    <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    
    <c:set var="baseURL" value="<%=request.getContextPath()%>"/>
    <html>
    
    <head>
     <title>Create a new employee</title>
     </head>
     
     <body>
     
     <a href="${baseURL}">Home</a>
     
     <br/><br/>
     
     <h3>Create new employee</h3>
     
     <form:form method="post" modelAttribute="employee" action="${baseURL}/save-employee">
     Name: <form:input path="name" type="text" /><br/><br/>
     Gender: <form:radiobuttons path="gender" items="${genders}"/><br/><br/>
     Date of birth: <form:input path="dateOfBirth"/> (mm/dd/yyyy)<br/><br/>
     <input type="submit" value="Save"/>
     </form:form>
     
     </body>
    
    </html>

    edit.jsp

    <%@ page isELIgnored="false" %>
    <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    
    <c:set var="baseURL" value="<%=request.getContextPath()%>"/>
    <html>
    
     <head>
     <title>Create a new employee</title>
     </head>
     
     <body>
     
     <a href="${baseURL}">Home</a>
     
     <br/><br/>
     
     <h3>Edit employee</h3>
     
     <form:form method="post" modelAttribute="employee" action="${baseURL}/update-employee">
     Name: <form:input path="name" type="text" /><br/><br/>
     Gender: <form:radiobuttons path="gender" items="${genders}"/><br/><br/>
     Date of birth: <form:input path="dateOfBirth"/> (mm/dd/yyyy)<br/><br/>
     <input type="submit" value="Update"/>
     </form:form>
     
     </body>
    
    </html>
    
    

    invalid.jsp

    <html>
    
    <head>
     <title>Invalid URL</title>
     </head>
     
     <body>
     
     <h3>You seems to entered an invalid URL</h3>
     
     Click <a href="/">here</a> for home page
     
     </body>
    
    </html>
  12. Now we are ready to run our application. Right click on project -> Run as -> Run on Server. Choose Tomcat or whatever server you want and you are ready to go.
  13. After running the application for the first time, make sure you change hibernate.hbm2ddl.auto in the persistence-mysql.properties file to validate instead of create otherwise it will create the database from start whenever you run your application.