Java Minute Maven 4: Spring MVC CRUD application with Hibernate and JPA repository

Introduction

In this tutorial we'll learn how to create Spring MVC web application with 4 basic actions: Create, Read, Update, Delete objects. We'll use Hibernate ORM and JPA Repository to manipulate data in database. Spring MVC will provide features for web development: routes, controllers, views and model. Maven will be used to manage dependencies. Spring configuration will be annotation-based.

Source code

This project is part of Java Minute series.

Github repository: rodionbykov/java-minute

Source code for this project: maven-4-spring-mvc-jpa-hibernate

Prerequisites

Please clone Java Minute repository and with your favorite IDE create new project in maven-4-spring-mvc-jpa-hibernate directory.

For this project I used Spring Tool Suite 3.7.2, JDK 1.8.0_66, MySQL 5.6.27, also worked in IDEA 15. Higher versions should be working fine too. I work under Windows 7 and 10, but had no problem to run project under Ubuntu Linux.

Tools: GitKraken, Github for Windows, Spring Tool Suite, IntelliJ IDEA, MySQL

Web Application descriptor file

The server running our web application should know about its details. For that purpose file web.xml is created under /WEB-INF directory. Root XML element of this descriptor file indicates Servlet specification version and associated schema, I've found some examples here. Usually this technical information can be generated using IDE. Main purpose of web.xml is to map URL to Servlet that will execute the request. Even if we will have Annotation based mapping configuration for this project, it doesn't mean we should remove web.xml from our project.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

        <display-name>spring-mvc-jpa-hibernate</display-name>
    
    <welcome-file-list>  
      <welcome-file>index.jsp</welcome-file>  
    </welcome-file-list>  
 
</web-app>

For more information please check docs from Google, Oracle, StackOverflow

Initialization

In order to have application started by Servlet Container (Tomcat), we have to create initialization code. This is done by Initializer class in init package. It implements WebApplicationInitializer interface, hooking up to onStartup method.

public class Initializer implements WebApplicationInitializer {  
      
    @Override  
    public void onStartup(ServletContext servletContext) throws ServletException {  
          
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();  
        ctx.register(WebAppConfig.class);            
        ctx.setServletContext(servletContext);    
          
        Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));  
        servlet.addMapping("/");  
        servlet.setLoadOnStartup(1);  
          
    }    
} 

In this code we tell Spring that we'll use Annotation-based config, without XML configuration, as well as Dispatcher Servlet will not use XML configuration.

See also: kielczewski.eu

Configuration

Since we had passed WebAppConfig.class as configuration for WebApplicationContext, let's define this class in same /init folder

package com.rodionbykov.init;

// imports were truncated

@Configuration
@EnableWebMvc
@EnableTransactionManagement
@ComponentScan("com.rodionbykov")
@PropertySource("classpath:application.properties")
@EnableJpaRepositories("com.rodionbykov.repository")
public class WebAppConfig {     }

First what can we see is that class annotated with @Configuration annotation, meaning that this class will provide Bean definitions using @Bean annotations instead of XML-based configuration. Bean definitions as well as Configuration class itself will be picked up during component scan. This allows to create Beans without manual instantiation using new keyword.

@EnableWebMvc as name suggests, enables Spring MVC in Spring application. This annotation  used to avoid XML-based configuration.

See this answer on Stack Overflow.

@ComponentScan sets up location where Spring will look for components - Configuration, Component, Controllers, Beans etc.

Configuration also can use key-value pairs provided in text file, which location is given after @PropertySource annotation. Injected Environment object will make use of properties set in application.properties file.

@Resource
private Environment env;

Like @Autowired and @Inject annotations, @Resource injects dependency, matching name, type or qualifiers. Good description of all three I've found here.

@EnableTransactionManagement and @EnableJpaRepositories used to enable Spring Data Repositories and Transaction management.

See also: Tutorials Point, Stack Overflow, Stack Overflow, Baeldung

Database setup

For this Java Minute I'm using MySQL 5. In database test please create table users (see readme.md for SQL statement). In resources/application.properties file write down connection parameters: name of driver, JDBC URL (for more information please check documentation), username and password.

Datasource

The first thing to do is to make a DataSource bean available to application. There are different ways to do this. For quick test, use Spring’s org.springframework.jdbc.datasource.DriverManagerDataSource to create a DataSource on demand.

@Bean
public DataSource dataSource() {
   DriverManagerDataSource dataSource = new DriverManagerDataSource();

   dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
   dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
   dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
   dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));

   return dataSource;
}

However, this creates a simple DataSource that returns single-use Connections. Because it does not provide connection re-use (pooling), it should not be used in a production environment. In a standalone application, you could use Apache Commons DBCP, Apache Commons Pool, or C3P0 to create and return a pooled DataSource. When using Application Server or Servlet Container, they could provide pooled Datasource to application. In Minute 5 I'll show how to use pooled Datasource using Tomcat JDBC Connection Pool. Usually, you would read a properties file with the URL, username, and password information so that changing the connection details won’t require a recompilation of code.

See also: Stack Overflow, MySQL

Persistence unit

Persistent Unit is a set of all entity classes that are managed by EntityManager. In WebAppConfig we had 3 Beans which are used for DB connectivity. Transaction manager bean uses Entity Manager Factory, which is using Datasource bean. Connection details are stored in properties file and are pulled by Environment object.

Object-relation mapping

First we need to describe simple Java object ("POJO") and them "map" it to database table ("relation" in terms of Relational Model). Use model package under root package to place User.java class, that will be linked to test.users DB table. To declare that object is used for ORM, use @Entity annotation, @Table and @Column are used to provide name of DB table and column names respectively. Use @Id annotation to mark identity (key) column.

More info: official documentation on Hibernate.

Views

We will use Java Server Pages (JSP) for presentation layer and have Bean configured for it in WebAppConfig:

@Bean
public UrlBasedViewResolver setupViewResolver() {
   UrlBasedViewResolver resolver = new UrlBasedViewResolver();
   resolver.setPrefix("/WEB-INF/views/");
   resolver.setSuffix(".jsp");
   resolver.setViewClass(JstlView.class);
   return resolver;
}

This means, that whenever View tempate is requested, Spring will check in /WEB-INF/views/ folder for appropriate .jsp file. For example, "list" view is displayed using list.jsp.

JSP template is being read by servlet container (Tomcat) and compiled into Servlet, which is executed by container. Dynamic elements can be inserted into tempate using <%%> construct. Variables can be inserted into template using ${variable} construct.

Standard Tag Library (JSTL) will be used with JSP. This library provides basic programming blocks like loops, conditionals, includes, and also HTML elements like forms to be used as custom tags inside JSP templates.


See also: Wikipedia, Oracle, Tutorials Point, Java.net

Project structure: