Spring boot supports JPA(Java Persistence API) for database related operations. It provides built in starter, which makes development easier and rapid. It also provides repositories, which gives built in support for most of the database related operations(like CRUD operations, find by methods, etc). In this article we will learn about how to use spring data JPA for database related CRUD(Create, Read, Update and Delete) operations.

In this example, we are going to create REST end points to support CRUD operations. We will use HTTP GET, PUT, POST and DELETE methods to implement the same. We will use Lombok to generate boiler plate codes, PostgreSQL database to store the values and Postman to test the REST end points.

Following are the version details

  • IDE: STS Version 4
  • Spring boot version : 2.1.5-RELEASE
  • Java version 1.8
  • Database : PostgreSQL 9.5
  • Lombok : For avoiding boiler plate codes.
  • Postman : For testing REST end points.

Following are the steps to create our Spring boot JPA CRUD application.

  • Create a Spring boot application with required starter dependencies.
  • Add database related configurations setup.
  • Create Entity class and Repository interface.
  • Create a service layer and a Rest(Representational State Transfer) controller layer.

Create a Spring boot application with required starter dependencies

First step is to create a spring boot application with required starter dependencies. In our case, we are going to create REST end points for CRUD operation using JPA. For this operation, we need to add spring-boot-starter-web, spring-boot-starter-data-jpa, lombok starter dependencies. You may find this link helpful to create new spring boot application.

In this example, I am creating a spring boot application with name : spring-boot-jpa-crud-example. I have used base package for the application : com.asb.example. Content of pom.xml file after creating the application is given below. I have also added dependency for postgreSQL. Project structure is also shown in the below image.

pom.xml

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.5.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.asb.example</groupId>
	<artifactId>spring-boot-jpa-crud-example</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-boot-jpa-crud-example</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
		<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
		<dependency>
		    <groupId>org.postgresql</groupId>
		    <artifactId>postgresql</artifactId>
		</dependency>
		
		
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

Project Structure

SpringBootJpaCrudExample.java

package com.asb.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootJpaCrudExampleApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringBootJpaCrudExampleApplication.class, args);
	}
}

Add database related configurations setup

Open the application.properties file under src/main/resources/ folder and add the following content. Here, we are setting up the database configuration with database username, password and url. We have disabled any SQL DDL operation execution by application by setting spring.jpa.hibernate.ddl-auto property to none. This prevents any table or schema creation or update from application side when it is started, as we are manually going to create database table.

application.properties

spring.datasource.url=jdbc:postgresql://localhost/postgres
spring.datasource.username=postgres
spring.datasource.password=asbnotebook

spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true

spring.jpa.hibernate.ddl-auto=none

spring.jpa.show-sql=true

Create a table called Employee by executing following script.

Here, we are creating a table to store Employee details in employee table. This table will have auto generated id column, and other text fields : designation, employee_code, employee_name as shown below.

CREATE TABLE employee
(
  id bigint NOT NULL,
  designation character varying(255),
  employee_code character varying(255),
  employee_name character varying(255),
  CONSTRAINT employee_pkey PRIMARY KEY (id)
)

Create Entity class and Repository interface

Now our database table is created, application is setup with database connection. Next step is to create an Entity class and map the database columns.

Create a new package com.asb.example.model and create a java class called Employee.java and add the following content. Here, we are annotating @Entity to make it an entity class. we have used @Table annotation to specify to which database table the class is mapped to. We have also used Lombok annotations for getters, setters and constructor’s creation.

Entity class contains all the database table fields mapped to corresponding entity class fields using @Column annotation. Id field is auto generated value, which is annotated with @Id and @GeneratedValue annotation, with generation strategy type as Identity.

Employee.java

package com.asb.example.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Entity
@AllArgsConstructor
@Getter
@Setter
@NoArgsConstructor
@Table(name="Employee")
public class Employee {

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="Id")
	private Long id;
	
	@Column(name="EmployeeName")
	private String employeeName;
	
	@Column(name="EmployeeCode")
	private String employeeCode;
	
	@Column(name="Designation")
	private String designation;
}

Create a package com.asb.example.repository and a EmployeeRepository.java interface and add the following content. Spring boot provides JpaRepository interface, which supports pagination and sorting of result set, and other common database operations. For our CRUD operation, we do not have to write any extra code, as CRUD operation is already supported by spring boot by default, as our EmployeeRepository interface is extending JpaRepository interface.

EmployeeRepository.java

package com.asb.example.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.asb.example.model.Employee;

public interface EmployeeRepository extends JpaRepository<Employee, Long> {

}

Create Service and Controller layers

It is always good practice to put our business logic inside service layer, which gives a layer of separation from controller and database related operations. Even though we are performing only CRUD operation, we are going to create a service layer in this example.

Create a new package com.asb.example.service, and create an interface called EmployeeService.java and define required methods as shown below. we have different methods defined for create, update, get employee by Id, delete and get all available employees from database.

EmployeeService.Java

package com.asb.example.service;
import java.util.List;
import com.asb.example.model.Employee;

public interface EmployeeService {

	public Employee createEmployee(Employee emp);
	public Employee updateEmployee(Employee emp);
	public Employee getEmployee(Long empId);
	public void deleteEmployee(Long empId);
	public List<Employee> getAllEmployee();
}

Create an implementation class for the created EmployeeService.java interface. Annotate the class with @Service annotation to register this class as spring service bean. We have also injected EmployeeRepository instance by using @Autowired annotation to perform database related operations. In this class, we have implementation for the defined interface methods.

EmployeeServiceImpl.java

package com.asb.example.service;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.asb.example.model.Employee;
import com.asb.example.repository.EmployeeRepository;

@Service
public class EmployeeServiceImpl implements EmployeeService {
	
	@Autowired
	private EmployeeRepository employeeRepository;

	@Override
	public Employee createEmployee(Employee emp) {
		return employeeRepository.save(emp);
	}

	@Override
	public Employee updateEmployee(Employee emp) {
		return employeeRepository.save(emp);
	}

	@Override
	public Employee getEmployee(Long empId) {
		Optional<Employee> optionalEmp =  employeeRepository.findById(empId);
		if(optionalEmp.isPresent()) {
			return optionalEmp.get();
		}
		return null;
	}

	@Override
	public void deleteEmployee(Long empId) {
		employeeRepository.deleteById(empId);
	}

	@Override
	public List<Employee> getAllEmployee() {
		return employeeRepository.findAll();
	}
}

Create a package com.asb.example.controller, and create a REST controller class with name EmployeeController.java as shown below. We have used @RestController annotation, which configures our class to behave as REST controller, which writes the response content to the response body. Here, we have different end points for CRUD operation.

EmployeeController.java

package com.asb.example.controller;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.asb.example.model.Employee;
import com.asb.example.service.EmployeeService;

@RestController
public class EmployeeController {

	@Autowired
	private EmployeeService employeeService;

	@PostMapping(consumes = "application/json", produces = "application/json", path = "/employee")
	public ResponseEntity<Employee> createEmployee(@RequestBody Employee emp) {
		return new ResponseEntity<>(employeeService.createEmployee(emp), HttpStatus.CREATED);
	}

	@PutMapping(consumes = "application/json", produces = "application/json", path = "/employee")
	public ResponseEntity<Employee> updateEmployee(@RequestBody Employee emp) {
		return new ResponseEntity<>(employeeService.updateEmployee(emp), HttpStatus.CREATED);
	}

	@DeleteMapping(produces = "application/json", consumes = "text/plain", path = "/employee/{empId}")
	public ResponseEntity<String> deleteEmployee(@PathVariable(value="empId") Long empId) {
		employeeService.deleteEmployee(empId);
		return new ResponseEntity<>("Employee with EmployeeId : " + empId + " deleted successfully", HttpStatus.OK);
	}

	@GetMapping(path = "/employee/{empId}", produces = "application/json")
	public ResponseEntity<Employee> getEmployee(@PathVariable(value = "empId") Long empId) {
		return new ResponseEntity<>(employeeService.getEmployee(empId), HttpStatus.OK);
	}

	@GetMapping(path = "/employees", produces = "application/json")
	public ResponseEntity<List<Employee>> getAllEmployees() {
		return new ResponseEntity<>(employeeService.getAllEmployee(), HttpStatus.OK);
	}
}

Running and testing the application

It’s time to test the REST end points now. To run the spring boot application, Right click on project > Run As > Spring Boot App. This will start our spring boot application on embedded tomcat server on default port 8080. Since we have not defined any application context, we can directly access the REST end points mentioned in each request mapping.

Create Example (POST Method) :

Open the postman and Fill the POST URL, to create a new employee record as shown below. Notice that request type is POST and the URL : http:localhost:8080/employee/ and request body contains the json content with employee details. Response is shown in the Response section, with created record along with id value.

Make sure that request headers Accept and Content-Type are set as shown below.

Value added in the database table is shown below.

Update Example (PUT Method) :

Request and response of update operation is shown below. Here, we have to pass the id column as well in the request, as JpaRepository’s save method updates the employee details based on Id input. In this example, we are updating the employee name with value ‘John’.

Updated employee name in database table is shown below.

Read By Id Example (GET Method) :

To fetch the stored employee details, we should use the HTTP GET method with URL : http:localhost:8080/employee/{empId}. Here, in below shown image, we are fetching the record of employee with Id 3.

Read All Employee Details (GET Method) :

This end point will fetch all the available records from database table. We are using HTTP GET method with URL : http:localhost:8080/employees. Here, below image shows two records, as i have created another employee record.

Delete Example (DELETE Method) :

For deleting the employee record, we are using HTTP DELETE method, with URL : http:localhost:8080/employee/{empId}. In the following example, we are passing the employee Id 4 to delete the record from database.

Congratulations!!! We created a spring boot application with REST CRUD operation end points. We have also used JPA to connect to PostgreSQL database and tested our end points using Postman.!! Good Job and Well done!! 😀 🙂

You may also interested in