Spring Boot PostgreSQL CRUD Example

In this tutorial, we will learn how to build CRUD REST APIs using Spring Boot, JPA/Hibernate, and the PostgreSQL database. We will use the latest version of Spring Boot in this tutorial.

Before development, make sure that the PostgreSQL database is installed on your machine.

Check out these two links to download and install a PostgreSQL database on your machine.

It's very easy to configure Spring Boot to use the PostgreSQL database. We are using Hibernate so which will support out-of-the-box to work with different database vendors without changing underlying code.

1. What we’ll build

We will build CRUD RESTFul APIs for a Simple Employee Management System using Spring Boot, JPA/Hibernate, and the PostgreSQL database. 
Following are five REST APIs (Controller handler methods) are created for Employee resource.

2. Tools and Technologies Used

  • Spring Boot
  • JDK - 1.8 or later
  • Spring Framework
  • Spring Data JPA (Hibernate)
  • Maven
  • IDE - Eclipse or Spring Tool Suite (STS)
  • PostgreSQL

3. Development Steps

Step 1: Create a Spring Boot Application
Step 2: Maven dependencies
Step 3: Configuring PostgreSQL Database
Step 4: Create JPA Entity - Employee.java
Step 5: Create a Spring Data Repository - EmployeeRepository.java
Step 6: Create Custom Exception
Step 7: Create Spring Rest Controller - EmployeeController.java
Step 8: Running Spring Boot Application
Step 9: Testing CRUD REST APIs via Postman Client

Step 1: Create a Spring Boot Application

Spring Boot provides a web tool called Spring Initializer to bootstrap an application quickly. Just go to https://start.spring.io/ and generate a new spring boot project.

spring boot

Use the below details in the Spring boot creation:

Project Name: springboot-backend

Project Type: Maven

Choose dependencies: Spring Web, Spring Data JPA, PostgreSQL, Dev Tools

Package name: net.javaguides.springboot

Step 2: Maven dependencies

Here is the complete pom.xml file for your reference:
<?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.5.3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>net.javaguides</groupId>
	<artifactId>springboot-backend</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>springboot-backend</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>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<scope>runtime</scope>
		</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>

Step 3: Configuring PostgreSQL Database

First, you need to create a database in the PostgreSQL server. You can use the following command to create a database in the PostgresSQL server:
CREATE DATABASE employees;
Now, let’s configure the Spring Boot application to use PostgreSQL as our data source. You can do that simply by adding PostgreSQL database URL, username, and password in the src/main/resources/application.properties file.

Open src/main/resources/application.properties file and add the following content to it:
spring.datasource.url=jdbc:postgresql://localhost:5432/employees
spring.datasource.username=postgres
spring.datasource.password=root
spring.jpa.show-sql=true

## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect

# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update

Make sure that you will change the above database configuration such as JDBC URL, username, and password as per your environment.
Hibernate will automatically create database tables so you only need to manually create the database and configure an application.properties file.

Step 4: Create JPA Entity - Employee.java

Let's create a new package called model inside net.javaguides.springboot package and then create the Employee class inside the model package with the following contents -
package net.javaguides.springboot.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;

@Entity
@Table(name = "employees")
public class Employee {
	
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private long id;
	
	@Column(name = "first_name")
	private String firstName;

	@Column(name = "last_name")
	private String lastName;
	
	@Column(name = "email_id")
	private String emailId;
	
	public Employee() {
		
	}
	
	public Employee(String firstName, String lastName, String emailId) {
		super();
		this.firstName = firstName;
		this.lastName = lastName;
		this.emailId = emailId;
	}
	public long getId() {
		return id;
	}
	public void setId(long id) {
		this.id = id;
	}
	public String getFirstName() {
		return firstName;
	}
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public String getEmailId() {
		return emailId;
	}
	public void setEmailId(String emailId) {
		this.emailId = emailId;
	}
}

Step 5: Create a Spring Data Repository - EmployeeRepository.java

Let's create a new package called repository inside net.javaguides.springboot package and then create the following interface inside the repository package -
package net.javaguides.springboot.repository;

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

import net.javaguides.springboot.model.Employee;

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

}

Step 6: Create Custom Exception

Let's create a new package called the exception inside net.javaguides.springboot base package. Within this package, create a ResourceNotFoundException class and add the following code to it:
package net.javaguides.springboot.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException{

	private static final long serialVersionUID = 1L;
	
	public ResourceNotFoundException(String message) {
		super(message);
	}
}

Step 7: Create Spring Rest Controller - EmployeeController.java

Let's create a controller package inside net.javaguides.springboot base package. Within this package, create an EmployeeController class and add the following code to it:
package net.javaguides.springboot.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
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 net.javaguides.springboot.exception.ResourceNotFoundException;
import net.javaguides.springboot.model.Employee;
import net.javaguides.springboot.repository.EmployeeRepository;

@CrossOrigin(origins = "http://localhost:4200")
@RestController
@RequestMapping("/api/v1/")
public class EmployeeController {

	@Autowired
	private EmployeeRepository employeeRepository;
	
	// get all employees
	@GetMapping("/employees")
	public List<Employee> getAllEmployees(){
		return employeeRepository.findAll();
	}		
	
	// create employee rest api
	@PostMapping("/employees")
	public Employee createEmployee(@RequestBody Employee employee) {
		return employeeRepository.save(employee);
	}
	
	// get employee by id rest api
	@GetMapping("/employees/{id}")
	public ResponseEntity<Employee> getEmployeeById(@PathVariable Long id) {
		Employee employee = employeeRepository.findById(id)
				.orElseThrow(() -> new ResourceNotFoundException("Employee not exist with id :" + id));
		return ResponseEntity.ok(employee);
	}
	
	// update employee rest api
	
	@PutMapping("/employees/{id}")
	public ResponseEntity<Employee> updateEmployee(@PathVariable Long id, @RequestBody Employee employeeDetails){
		Employee employee = employeeRepository.findById(id)
				.orElseThrow(() -> new ResourceNotFoundException("Employee not exist with id :" + id));
		
		employee.setFirstName(employeeDetails.getFirstName());
		employee.setLastName(employeeDetails.getLastName());
		employee.setEmailId(employeeDetails.getEmailId());
		
		Employee updatedEmployee = employeeRepository.save(employee);
		return ResponseEntity.ok(updatedEmployee);
	}
	
	// delete employee rest api
	@DeleteMapping("/employees/{id}")
	public ResponseEntity<Map<String, Boolean>> deleteEmployee(@PathVariable Long id){
		Employee employee = employeeRepository.findById(id)
				.orElseThrow(() -> new ResourceNotFoundException("Employee not exist with id :" + id));
		
		employeeRepository.delete(employee);
		Map<String, Boolean> response = new HashMap<>();
		response.put("deleted", Boolean.TRUE);
		return ResponseEntity.ok(response);
	}
}

Enable CORS on the Server

To enable CORS on the server, add a @CrossOrigin annotation to the EmployeeController:
@CrossOrigin(origins = "http://localhost:4200")
@RestController
@RequestMapping("/api/v1/")
public class EmployeeController {
// ..
}

Step 8: Running Spring Boot Application

This spring boot application has an entry point Java class called SpringbootBackendApplication with the public static void main(String[] args) method, which you can run to start the application.

package net.javaguides.springboot;

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

@SpringBootApplication
public class SpringbootBackendApplication {

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

}
Or you can start the spring boot application via the command line using mvn spring-boot:run command.

Once Spring boot application is up and running, then you can check the PostgreSQL database:

Step 9: Testing CRUD REST APIs via Postman Client

1. Create Employee REST API

HTTP Method: POST 
Note that request and response JSON in the above diagram, the response contains a database auto-generated id.

2. Get Employee by ID REST API

HTTP Method: GET 

3. Get all Employees REST API

HTTP Method: GET 

4. Update Employee REST API

HTTP Method: GET 

5. Delete Employee REST API

HTTP Method: DELETE 

Conclusion

In this tutorial, we have learned how to build CRUD REST APIs using Spring Boot, JPA/Hibernate, and the PostgreSQL database. We have used the latest version of Spring Boot in this tutorial.

Comments