Spring MVC With JPA
JPA (Java Persistence API) is an API that works as a bridge between Java application and Relational database. It is a set of classes and interfaces that are used to perform database operations efficiently. It reduces the effort of database configuration in Java application and supported by all the major databases MySQL, Oracle, Redhat, etc.
Originally, JPA was released combined with EJB as a business logic layer and can be accessed using javax.ejb.EntityBean
Interface. but now various products having the JPA persistence flavor in them such as Hibernate, Spring Data JPA, etc.
In this article, we will learn to use JPA in Spring application and connect with the database(MySQL). The following image shows the structure and file hierarchy of our Maven-based Spring project.
Project Structure
// RegisterController.java
This is our controller class that has two methods index() and save(). The first is used to return a JSP page as a user form and the second is used to save the user details into the database.
package com.studytonight.controllers;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
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.studytonight.models.User;
import com.studytonight.service.UserService;
@Controller
public class RegisterController{
@Autowired
private UserService userService;
@GetMapping("/")
public String index() {
return "register";
}
@PostMapping("save")
public String save(@Valid @ModelAttribute User user, BindingResult result) {
if(result.hasErrors()) {
return "register";
}else {
userService.register(user);
return "successful";
}
}
}
// user.java
This is our entity class that represents the User table structure in the database. We used @Entity annotation to mark it as an Entity. The Spring will create a User table into the MySQL database.
package com.studytonight.models;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue
private Long id;
private String name;
private Long mobile;
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 Long getMobile() {
return mobile;
}
public void setMobile(Long mobile) {
this.mobile = mobile;
}
}
// UserRepository.java
It is an interface for DAO implementation. It contains a single save() method.
package com.studytonight.repository;
import com.studytonight.models.User;
public interface UserRepository {
User save(User user);
}
// UserRepositoryImpl.java
It is our DAO(Data Access Object) implementation class that performs database operations. In our case, we are inserting user data into table so the persist()
method of EntityManager is used.
package com.studytonight.repository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.studytonight.models.User;
@Component
@Repository
public class UserRepositoryImpl implements UserRepository{
@PersistenceContext
private EntityManager em;
@Override
@Transactional
public User save(User user) {
em.persist(user);
em.flush();
return user;
}
}
// UserService.java
It is an interface for service class implementation. It contains a single method register().
package com.studytonight.service;
import org.springframework.stereotype.Service;
import com.studytonight.models.User;
public interface UserService {
User register(User user);
}
// UserServiceImpl.java
It is our service implementation class that called DAO's save() method to save the user data.
package com.studytonight.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.studytonight.models.User;
import com.studytonight.repository.UserRepository;
@Component
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserRepository userRepository;
@Override
@Transactional
public User register(User user) {
// TODO Auto-generated method stub
return userRepository.save(user);
}
}
These XML files are Java persistance API configuration files that contains connection details, database dialects and EntityManagerFactory configuration.
// persistance.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="punit"></persistence-unit>
</persistence>
// jpaContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:annotation-config />
<context:component-scan
base-package="com.studytonight"></context:component-scan>
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="datasource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver"></property>
<property name="url"
value="jdbc:mysql://localhost:3306/springwithdb?autoReconnect=true"></property>
<property name="username" value="root_user" />
<property name="password" value="root_password" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="punit" />
<property name="dataSource" ref="datasource" />
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
</bean>
</property>
<!-- JPA vendor properties: specific to Hibernate, in our case -->
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.dialect"
value="org.hibernate.dialect.MySQLDialect" />
<entry key="hibernate.hbm2ddl.auto" value="create"></entry>
<entry key="hibernate.format_sql" value="true"></entry>
</map>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven />
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
</beans>
// register.jsp
This is a JSP page that contains an HTML form and renders when the application starts.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>User Registration Form</title>
</head>
<body>
<h2>User Registration Form</h2>
<form action="save" method="post">
<label>User Name : </label> <input type="text" name="name"><br>
<br> <label>Mobile : </label> <input type="text" name="mobile"><br>
<br> <input type="submit" value="Register">
</form>
</body>
</html>
// successful.jsp
This JSP page shows a success page when user registers successfuly.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title></title>
</head>
<body>
<h2>Registered Successfully!</h2>
</body>
</html>
// servletConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- Step 3: Add support for component scanning -->
<context:component-scan base-package="com.studytonight.controllers" />
<!-- Step 4: Add support for conversion, formatting and validation support -->
<mvc:annotation-driven/>
<!-- Step 5: Define Spring MVC view resolver -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
// web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>springwithdb</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classPath:/jpaContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring MVC Configs -->
<!-- Step 1: Configure Spring MVC Dispatcher Servlet -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/servlet-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Step 2: Set up URL mapping for Spring MVC Dispatcher Servlet -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
pom.xml
This file contains all the dependencies of this project such as spring jars, servlet jars, etc. Put these dependencies into your project to run the application.
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.studytonight</groupId>
<artifactId>springwithdb</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.1.Final</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0.pr3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.1.4.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.1.9.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.transaction/jta -->
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
</dependency>
</dependencies>
<properties>
<spring.version>5.2.8.RELEASE</spring.version>
</properties>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.3</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project>
Run the Application
After successfully completing the project and adding the dependencies run the application and you will get the output as below.
When a user is successfully registered then data will be stored in the user table that you can verify by accessing your database.