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); } }
Clearly explained Sir. I’m working on a similar project where I should post, put, delete and get Customer details from database, but the thing is when I try to post, the program have to check whether the customer name starts with char ‘A'(ie, index 0 must be A) , if yes, then the customer details can be uploaded but if the customer name doesn’t start with ‘A’ then the program should raise a error message.
Can you please help me to solve this problem. Thanks in advance.