Spring Boot, MySQL, JPA, Hibernate Restful CRUD API Tutorial [2021]





Hey guys in this post, we will learn about creating REST API with Spring Boot, MySQL, JPA, and Hibernate. We will also perform the basic CRUD (Create, Read, Update, Delete) operations.

Spring framework is one of the most popular frameworks in the entire java ecosystem. More than 90% of java enterprise applications using the Spring framework in their production.

Spring Boot is a tool to create Spring applications with zero configuration. Spring boot is getting popular day by day that is because you can create REST APIs and Microservices in no time.

JPA is a Java Persistence API, is the most popular data accessor API. It is also getting popular day by day. Almost all the spring boot applications using JPA to access the database data access layer. JPA is just a standard/specification and Hibernate is the implementation.

Application features


So as part of this tutorial, we will be creating a Customer Relationship Management (CRM) API, it has the following features –

  • Create customer
  • Read single customer
  • Read all customers
  • Update customer
  • Delete customer

Let’s see the rest endpoints for the above features –

Video tutorial


Development steps


Following are the development steps to create the spring boot REST API.




Create spring boot application


There are different ways to create a spring boot application. You can pick any one of the following ways to create –

>> Create spring boot application using Spring initializer
>> Create spring boot application in Spring tool suite [STS]
>> Create spring boot application in IntelliJ IDEA

Update maven dependencies


Once the project is created open pom.xml and add the following maven dependencies

<?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>2.4.2</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>in.bushansirgur</groupId>
	<artifactId>springdatarest</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>employeerestapi</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>1.8</java.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.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
                <dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</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>

Configure database


As we have added MySQL dependency to the pom.xml, so let’s configure the database URL, username, and password. We will also configure hibernate properties for auto-creating the tables based on the entity. Open application.properties and add the following code –

spring.datasource.url=jdbc:mysql://localhost:3306/springdatajpa
spring.datasource.username=springbootapps
spring.datasource.password=springbootapps

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

Note that, change the spring.datasource.username adn spring.datasource.password as per your MySQL installation. Also, create a database with the name springdatajpa

Create an entity


Create Customer.java class inside the in.bushansirgur.springdatajpa.entity package and add the following fields

package in.bushansirgur.springdatajpa.entity;

import java.util.Date;

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 org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Entity
@Table(name="tbl_customer")
@Setter
@Getter
@ToString
public class Customer {
	
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Long id;
	
	private String name;
	
	private Long age;
	
	private String location;
	
	@CreationTimestamp
	@Column(name="created_at", nullable=false, updatable=false)
	private Date createdAt;
	
	@UpdateTimestamp
	@Column(name="updated_at")
	private Date updatedAt;
	
}

@Entity annotation must be added to the entity class, it tells that the entity class is mapped to the database table

@Table annotation is added to tell the name of the table to which the class is mapped to.

@Id annotation is added to make the field uniquely identified, its nothing but the primary key

@GeneratedValue annotation is added for auto-generating the primary key




@Column annotation is added to specify the column name. If you don’t provide @Column annotation then the field name will become the column name.

@CreationTimestamp annotation automatically adds the current date-time when a new object is created

@UpdateTimestamp annotation automatically adds the current date-time when an existing object is updated.

@Setter is a Lombok annotation, which will generate the setters. Similarly, @Getter will generate the getters and @ToString will override the toString()

Create JPA repository


Create ICustomerRepo.java interface inside the package in.bushansirgur.springdatajpa.repository and add the following code

package in.bushansirgur.springdatajpa.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import in.bushansirgur.springdatajpa.entity.Customer;

@Repository
public interface ICustomerRepo extends JpaRepository<Customer, Long> {

}

Spring Data JPA comes with several interfaces to access the database, one of the interfaces is JpaRepository, it provides some of the useful methods to perform the database operations such as Create, Read, Update and Delete

Create customer service and service implementation


Create ICustomerService.java interface inside in.bushansirgur.springbootjpa.service package and add the following code –

package in.bushansirgur.springdatajpa.service;

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

import in.bushansirgur.springdatajpa.entity.Customer;

public interface ICustomerService {
	
	Customer add(Customer customer);
	
	List get();
	
	Optional get(Long id);
	
	void delete(Long id);
}

So we have defined 4 methods to perform the database operations. Let’s create an implementation class.

Create CustomerServiceImpl.java class inside in.bushansirgur.springbootjpa.service package and add the following code –

package in.bushansirgur.springdatajpa.service;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import in.bushansirgur.springdatajpa.entity.Customer;
import in.bushansirgur.springdatajpa.repository.ICustomerRepo;

@Service
public class CustomerServiceImpl implements ICustomerService {

	@Autowired
	ICustomerRepo customerRepo;
	
	@Override
	public Customer add(Customer customer) {
		return customerRepo.save(customer);
	}

	@Override
	public List get() {
		return customerRepo.findAll();
	}

	@Override
	public Optional get(Long id) {
		return customerRepo.findById(id);
	}

	@Override
	public void delete(Long id) {
		if (get(id).isPresent()) {
			customerRepo.delete(get(id).get());
		}
	}

}

Create a controller to handle requests


Create CustomerController.java class inside in.bushansirgur.springbootjpa.controller package and add the following code


package in.bushansirgur.springdatajpa.controller;

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

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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import in.bushansirgur.springdatajpa.entity.Customer;
import in.bushansirgur.springdatajpa.service.ICustomerService;

@RestController
@RequestMapping("/api")
public class CustomerController {

	@Autowired
	ICustomerService customerService;
	
	@GetMapping("/customers")
	public ResponseEntity<List<Customer>> getAllCustomers() {
		try {
			List<Customer> list = customerService.get();
			
			if (list.isEmpty() || list.size() == 0) {
				return new ResponseEntity<>(HttpStatus.NO_CONTENT);
			}
			
			return new ResponseEntity<>(list, HttpStatus.OK);
		} catch (Exception e) {
			return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
		}
	}
	
	@GetMapping("/customers/{id}")
	public ResponseEntity<Customer> getCustomer(@PathVariable Long id) {
		Optional<Customer> customer = customerService.get(id);
		
		if (customer.isPresent()) {
			return new ResponseEntity<Customer>(customer.get(), HttpStatus.OK);
		}
		return new ResponseEntity<Customer>(HttpStatus.NOT_FOUND);
	}
	
	@PostMapping("/customers")
	public ResponseEntity<Customer> saveCustomer(@RequestBody Customer customer) {
		try {
			return new ResponseEntity<Customer>(customerService.add(customer), HttpStatus.CREATED);
		} catch (Exception e) {
			return new ResponseEntity<Customer>(HttpStatus.INTERNAL_SERVER_ERROR);
		}
	}
	
	@PutMapping("/customers")
	public ResponseEntity<Customer> updateCustomer(@RequestBody Customer customer) {
		try {
			return new ResponseEntity<Customer>(customerService.add(customer), HttpStatus.OK);
		} catch (Exception e) {
			return new ResponseEntity<Customer>(HttpStatus.INTERNAL_SERVER_ERROR);
		}
	}
	
	@DeleteMapping("/customers/{id}")
	public ResponseEntity<HttpStatus> deleteCustomer(@PathVariable Long id) {
		try {
			customerService.delete(id);
			return new ResponseEntity<>(HttpStatus.NO_CONTENT);
		} catch (Exception e) {
			return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
		}
	}
}

Run the application


Now we have created the REST API for customer relationship management. It’s time to run the application. There are two ways to run the spring boot application

  • By executing the maven command from the root of the application
$ mvn spring-boot:run
  • By running the java class

Open SpringdatajpaApplication.java class, it has a main() method. Run the file just like running any other java class.

In a few seconds, the application will start running on port 8080 (localhost:8080)

Test the REST API


We cannot test all the rest endpoints inside the browser. Instead, we will use Postman to test all of the rest endpoints.

  • POST /api/customers
  • GET /api/customers
  • GET /api/customers/2
  • GET /api/customers/5




  • PUT /api/customers
  • DELETE /api/customers/2




About the author

Bushan Sirgur

Well, I am Bushan Sirgur from Banglore, India. Currently, I am working as a Software Developer in a Service Base Company. I am interested in JAVA/J2EE, Angular 2, JavaScript, jQuery, MongoDB.

View all posts

Leave a Reply

Your email address will not be published. Required fields are marked *