Spring Boot CRUD REST API with MySql

Here is an example of the REST API using spring boot with MySql as the database. We have used a single table of Employee, with custom exception handler to give users readable error messages.

Directory structure

Model Class (employee.java)

package com.loopandbreak.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 javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;

@Entity
@Table(name = "employees")
public class Employee {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private long id;

	@Column(name = "first_name")
	@NotNull
	private String firstName;

	@Column(name = "last_name")
	@NotNull
	private String lastName;

	@Column(name = "email")
	@NotNull
	@Email
	private String email;

	public Employee() {
	}

	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 getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}
}

Employee Repo (EmployeeRepository.java)

package com.loopandbreak.repos;

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

import com.loopandbreak.model.Employee;

public interface EmployeeRepository extends JpaRepository<Employee, Long> {
	Employee findByEmail(String email);
}

Employee Service interface (EmployeeService.java)

package com.loopandbreak.services;

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

import com.loopandbreak.model.Employee;

public interface EmployeeService {

	List<Employee> getAllEmployees();

	Optional<Employee> getEmployeeById(Long employeeId);

	void addEmployee(Employee employee);
	
	Employee getEmployeeByEmail(String email);

	void deleteEmployee(Long idOfEmployee);

}

Employee Service interface (EmployeeServiceImpl.java)

package com.loopandbreak.servicesimpl;

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

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

import com.loopandbreak.model.Employee;
import com.loopandbreak.repos.EmployeeRepository;
import com.loopandbreak.services.EmployeeService;

@Service
public class EmployeeServiceImpl implements EmployeeService {

	@Autowired
	private EmployeeRepository employeeRepository;

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

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

	@Override
	public void addEmployee(Employee employee) {
		employeeRepository.save(employee);
	}

	@Override
	public Employee getEmployeeByEmail(String email) {
		Employee employeeExists = employeeRepository.findByEmail(email);		
		return employeeExists;
	}

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

Employee Controller (EmployeeController.java)

package com.loopandbreak.controllers;

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

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
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 com.loopandbreak.exceptions.EmployeeAlreadyExists;
import com.loopandbreak.exceptions.EmployeeNotFoundException;
import com.loopandbreak.model.Employee;
import com.loopandbreak.servicesimpl.EmployeeServiceImpl;

@RestController
@RequestMapping("/api/v1")
public class EmployeeController {

	@Autowired
	private EmployeeServiceImpl employeeServiceImpl;

	@GetMapping("/employees")
	public ResponseEntity<List<Employee>> listEmployees() {
		List<Employee> employees = employeeServiceImpl.getAllEmployees();

		if (employees.isEmpty()) {
			return new ResponseEntity<List<Employee>>(HttpStatus.NO_CONTENT);
		}

		return new ResponseEntity<List<Employee>>(employees, HttpStatus.OK);
	}

	@GetMapping("/employees/{id}")
	public ResponseEntity<Employee> getEmployeeById(@PathVariable(value = "id") final Long employeeId) {
		Optional<Employee> employee = employeeServiceImpl.getEmployeeById(employeeId);

		if (!employee.isPresent()) {
			return new ResponseEntity<Employee>(HttpStatus.NOT_FOUND);
		}
		return new ResponseEntity<Employee>(employee.get(), HttpStatus.OK);

	}

	@PostMapping(value = "/employees", consumes = MediaType.APPLICATION_JSON_VALUE)
	public ResponseEntity<Employee> createUser(@Valid @RequestBody final Employee employee)
			throws EmployeeAlreadyExists {

		Employee ifEmployeeExists = employeeServiceImpl.getEmployeeByEmail(employee.getEmail());

		if (ifEmployeeExists != null) {
			throw new EmployeeAlreadyExists("A user with email already exists");
		}

		employeeServiceImpl.addEmployee(employee);
		return new ResponseEntity<Employee>(employee, HttpStatus.CREATED);
	}

	@PutMapping(value = "/employees/{id}", consumes = MediaType.APPLICATION_JSON_VALUE)
	public ResponseEntity<Employee> updateUser(@PathVariable("id") final Long id,
			@Valid @RequestBody final Employee employee) throws EmployeeNotFoundException {

		Optional<Employee> emp = employeeServiceImpl.getEmployeeById(id);

		if (!emp.isPresent()) {
			throw new EmployeeNotFoundException("No employee found for name " + employee.getFirstName());
		}

		emp.get().setFirstName(employee.getFirstName());
		emp.get().setLastName(employee.getLastName());
		emp.get().setEmail(employee.getEmail());

		employeeServiceImpl.addEmployee(emp.get());

		return new ResponseEntity<Employee>(HttpStatus.ACCEPTED);
	}

	@DeleteMapping("/employees/{id}")
	public Map<String, Boolean> deleteEmployee(@PathVariable(value = "id") Long employeeId)
			throws EmployeeNotFoundException {
		Optional<Employee> emp = employeeServiceImpl.getEmployeeById(employeeId);

		if (!emp.isPresent()) {
			throw new EmployeeNotFoundException("Employee not found for employee Id " + employeeId);
		}

		employeeServiceImpl.deleteEmployee(employeeId);
		Map<String, Boolean> response = new HashMap<String, Boolean>();

		response.put("deleted", Boolean.TRUE);
		return response;
	}
}

Exception handlers

package com.loopandbreak.exceptions;

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

@ResponseStatus(value = HttpStatus.CONFLICT)
public class EmployeeAlreadyExists extends Exception {

	private static final long serialVersionUID = 1L;

	public EmployeeAlreadyExists(String exceptionContent) {
		super(exceptionContent);
	}

}
package com.loopandbreak.exceptions;

public class EmployeeNotFoundException extends Exception {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public EmployeeNotFoundException(String message)
	{
		super(message);
	}

}
package com.loopandbreak.exceptions;

import java.util.Date;

public class ErrorDetails {

	private Date timestamp;
	private String message;
	private String details;

	public ErrorDetails(Date timestamp, String message, String details) {
		this.timestamp = timestamp;
		this.message = message;
		this.details = details;
	}

	public Date getTimestamp() {
		return timestamp;
	}

	public String getMessage() {
		return message;
	}

	public String getDetails() {
		return details;
	}

}
package com.loopandbreak.exceptions;

import java.util.Date;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler{
	
	@ExceptionHandler(EmployeeAlreadyExists.class)
	public ResponseEntity<?> exployeeAlreadyExistsException(EmployeeAlreadyExists alreadyExists, WebRequest request)
	{
		ErrorDetails errorDetails = new ErrorDetails(new Date(), alreadyExists.getMessage(), request.getDescription(false));
		return new ResponseEntity<>(errorDetails, HttpStatus.CONFLICT);		
	}
		
	@ExceptionHandler(EmployeeNotFoundException.class)
	public ResponseEntity<?> exployeeNotFoundException(EmployeeNotFoundException employeeNotFoundException, WebRequest request)
	{
		ErrorDetails errorDetails = new ErrorDetails(new Date(), employeeNotFoundException.getMessage(), request.getDescription(false));
		return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);		
	}
	
}

Main Application Class

package com.loopandbreak;

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

@SpringBootApplication
public class EmployeeApplication {

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

Inserting record into DB

Getting all records

Selecting single record

Updating Record

Leave a Reply

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