Restful API using Spring Rest + Spring Data JPA + H2 with Spring Boot Example

Hello Friends,

In this tutorial, you will learn the following :

- Configuring Spring Rest, Spring Data JPA and H2 in Spring Boot
- Example of Spring Rest, Spring Data JPA, and H2 to create restful services endpoints with Spring Boot
- Using Swagger to test the Restful endpoints

1. Configuring Spring Rest, Spring Data JPA and H2 in Spring Boot

Go to https://start.spring.io/ and create a project with name spring-rest-and-data-jpa-with-springboot and with following dependencies :

- Web
- JPA
- H2



Note: If you are not familiar with creating Spring Boot project with Spring Initializer, I would recommend following one of my previous posts, How to Create Spring Boot Project with Spring Initializer where I have explained in detail,how we can create a Spring Boot project using Spring Initializer.

2. Example of Spring Rest, Spring Data JPA, and H2 to create restful services endpoints with Spring Boot

In this example, We are going to create Rest endpoints to 

- Create Employee resource

- Retrieve List of Employees 

- Retrieve Employee

- Update Employee resource

- Delete Employee resource

Following is the FINAL directory structure of the project :




Let us see the various classes and interfaces that we need to create.

Step 1

Export project spring-rest-and-data-jpa-with-springboot(that you created via Spring Initializer)from your directory to Eclipse.

Step 2 

Open pom.xml.
It should have all the dependencies that you added from spring initializer website along with some default dependencies.

Also, I have manually added dependencies to enable Swagger. Swagger is basically used to test rest endpoints.
<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.0.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.blogspot.javasolutionsguide</groupId>
<artifactId>spring-rest-and-data-jpa-with-springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>

<properties>
<java.version>21</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-h2console</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>3.0.2</version>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc-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>

Step 3

Spring boot has created a java file with name SpringRestAndDataJpaWithSpringBootApplication automatically. This class is used to launch a Spring Boot application. 

package com.blogspot.javasolutionsguide.spring_rest_and_data_jpa_with_springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringRestAndDataJpaWithSpringbootApplication {

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

Step 4

Create Employee entity.
package com.blogspot.javasolutionsguide.spring_rest_and_data_jpa_with_springboot.entity;

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

@Entity
@Table(name = "EMPLOYEE")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "EMPLOYEE_NAME")
private String name;

@Column(name = "EMPLOYEE_SALARY")
private Integer salary;

@Column(name = "DEPARTMENT")
private String department;

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 Integer getSalary() {
return salary;
}

public void setSalary(Integer salary) {
this.salary = salary;
}

public String getDepartment() {
return department;
}

public void setDepartment(String department) {
this.department = department;
}
}

Step 5

Create Rest Controller with all operations.
package com.blogspot.javasolutionsguide.spring_rest_and_data_jpa_with_springboot.controller;

import com.blogspot.javasolutionsguide.spring_rest_and_data_jpa_with_springboot.entity.Employee;
import com.blogspot.javasolutionsguide.spring_rest_and_data_jpa_with_springboot.service.EmployeeService;
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 java.util.List;
import java.util.Optional;

@RestController
public class EmployeeRestController {
private final EmployeeService employeeService;

public EmployeeRestController(EmployeeService employeeService) {
this.employeeService = employeeService;
}

@GetMapping("/api/employees")
public List<Employee> getEmployees() {
return employeeService.retrieveEmployees();
}

@GetMapping("/api/employees/{employeeId}")
public ResponseEntity<Employee> getEmployee(@PathVariable(name = "employeeId") Long employeeId) {
return employeeService.getEmployee(employeeId)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound()
.build());
}

@PostMapping("/api/employees")
public void saveEmployee(@RequestBody Employee employee) {
employeeService.saveEmployee(employee);
System.out.println("Employee Saved Successfully");
}

@DeleteMapping("/api/employees/{employeeId}")
public void deleteEmployee(@PathVariable(name = "employeeId") Long employeeId) {
employeeService.deleteEmployee(employeeId);
System.out.println("Employee Deleted Successfully");
}

@PutMapping("/api/employees/{employeeId}")
public ResponseEntity<Employee> updateEmployee(@RequestBody Employee employee,
@PathVariable(name = "employeeId") Long employeeId) {
Optional<Employee> emp = employeeService.getEmployee(employeeId);
if (emp.isEmpty()) {
return ResponseEntity.notFound()
.build();
}
employee.setId(employeeId);
Employee updatedEmployee = employeeService.updateEmployee(employee);
return ResponseEntity.ok(updatedEmployee);
}
}

Step 6

Create Service interface with methods required to retrieve the list of employees, one employee, save employee in the database, delete an employee and update and employee.

package com.blogspot.javasolutionsguide.spring_rest_and_data_jpa_with_springboot.service;

import com.blogspot.javasolutionsguide.spring_rest_and_data_jpa_with_springboot.entity.Employee;

import java.util.List;
import java.util.Optional;

public interface EmployeeService {
public List<Employee> retrieveEmployees();

public Optional<Employee> getEmployee(Long employeeId);

public void saveEmployee(Employee employee);

public void deleteEmployee(Long employeeId);

public Employee updateEmployee(Employee employee);
}

Step 7

Create Implementation class for the interface created in Step 6.
package com.blogspot.javasolutionsguide.spring_rest_and_data_jpa_with_springboot.service.impl;

import com.blogspot.javasolutionsguide.spring_rest_and_data_jpa_with_springboot.entity.Employee;
import com.blogspot.javasolutionsguide.spring_rest_and_data_jpa_with_springboot.repository.EmployeeRepository;
import com.blogspot.javasolutionsguide.spring_rest_and_data_jpa_with_springboot.service.EmployeeService;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

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

public EmployeeServiceImpl(EmployeeRepository employeeRepository) {
this.employeeRepository = employeeRepository;
}

public List<Employee> retrieveEmployees() {
return employeeRepository.findAll();
}

public Optional<Employee> getEmployee(Long employeeId) {
return employeeRepository.findById(employeeId);
}

public void saveEmployee(Employee employee){
employeeRepository.save(employee);
}

public void deleteEmployee(Long employeeId){
employeeRepository.deleteById(employeeId);
}

public Employee updateEmployee(Employee employee) {
return employeeRepository.save(employee);
}
}

Step 8

Create a repository interface, which will extend Spring data JPA JpaRepository and hence will provide the methods to perform CRUD operations out of the box.

package com.blogspot.javasolutionsguide.spring_rest_and_data_jpa_with_springboot.repository;

import com.blogspot.javasolutionsguide.spring_rest_and_data_jpa_with_springboot.entity.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface EmployeeRepository extends JpaRepository<Employee,Long> {

}

Step 9 

Enable the H2 database web console by adding the following lines in the application.properties file
spring.h2.console.enabled=true
spring.h2.console.path=/h2
Spring Boot will automatically take care of the creation of the data source for H2 database, however we can manually configure data source as well in the application.properties file as following :
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver

Step 10

With this you are done with creation of your restful API using Spring Rest,spring data JPA with h2 database.

Now you just need to run your SpringRestAndDataJpaWithSpringBootApplication.java class and it will make sure that it will build your code, package your code in the jar and deploy it onto the embedded tomcat server.

Step 11

Open H2 database console by hitting following URL 

http://localhost:8080/h2/

It will show you the following screen :


Click on the Connect button and it will connect you to the H2 database. and you can see that the  EMPLOYEE table has been created, but there is no data in this table, which is as we expected.       



3. Using Swagger to test the Restful endpoints

To test your rest endpoints, hit the Swagger URL follows :

http://localhost:8080/swagger-ui/index.html

It will open the following page



Now we can see five endpoints in the above screenshot. We will test them one by one.

Save Employee - /api/employees

The first thing we need to do is to create a resource in the database. 
For that we will use POST operation and use /api/employees endpoint.




Click on the down arrow and click on Try it out:





Remove "id" and its value from payload as it will automatically generated by JPA provider, fill rest of the fields data and click on execute.

This is how your request and response will look like


















As you can see that the response code is 200, which means SUCCESS and hence our record should have been created in the H2 database.

Let us check that.

Open H2 web console and query the EMPLOYEE table and you can see the record that we pushed from Swagger UI.



                                                                                                                      
Similarly, Insert one more employee from Swagger UI with the following data :


















Query database again and you will see two records in the database as follows :






Get Employees - /api/employees

Now as we have already inserted two records  in the database, we will try to retrieve these records with the help of GET operation and using /api/employees endpoint as follows :



























Get Employee - /api/employees/{employeeId}

Next, we will retrieve only one employee on the basis of input employeeId using GET operation. We will pass employeeId to the rest endpoint /api/employees/{employeeId}.








Update Employee -  /api/employees/{employeeId}

Next, we will test the update employee rest endpoint using PUT operation and by using /api/employees/{employeeId} endpoint.







Verify updated record with updated salary to 3000 from 1000 in the EMPLOYEE table in H2 database for employee with employeeId 1.




Delete Employee - - /api/employees/{employeeId}

Next, we will test the delete Employee rest endpoint using DELETE operation and be using /api/employees/{employeeId} endpoint.
























Let us verify if an employee with employeeId 1 has been successfully deleted from the database by opening H2 console and querying database.




















As we can see above screenshot that we don't get record with ID = 1 now, hence employee with employeeId 1 has been successfully deleted.

Summary

So in the above post, we saw how we can create restful API using Spring rest, Spring Data JPA and H2 database with Spring Boot.

We need to 
- Create Spring Boot project from spring Initializer with required dependencies.
- Enable swagger support by adding additional dependencies in POM.xml and adding annotation in the spring boot application class.
- Enable the H2 database by adding necessary properties in the application.properties.
- Write Rest Controller, Service, repository and entity to work upon.
- Start Spring boot application, which will be automatically deployed to an embedded server.
- Test the rest endpoints using Swagger UI and verify data in the H2 database using the H2 console.