Create CRUD Rest API using Spring Boot and JPA

This java rest api tutorial help to create CRUD rest api using spring boot application.The spring boot is the next level of spring framework.Its based on java spring framework.We will create maven type project and generating JAR build.

The Spring boot provides CLI to create and manage application.You can setup a spring boot project with almost zero configuration.

In this java rest tutorial, we’ll build a Restful CRUD API for employee module.This module have API to get all employee, get a single employee records based on id and delete employee record by id.

How To Create a New Spring Boot Project

The spring boot provides a web tool to create initial level spring boot application.We will go to https://start.spring.io/, Now enter the required details.
create-spring-boot-project
Once all the details are entered, You need to click Generate Project button to generate and download your project.The downloaded project structure in zip file, unzip this folder and placed into your java_workplace or import into
your favorite IDE.

Following is the directory structure of our Employee spting boot application –spring-boot-file-structure

Spring Boot Main Entry file

Each java application is have the main entry point to execute application. We have com/example/restapiexample/SpringBootCrudExampleApplication.java file for main entry java application.

Create MySQL Table

We are taking MySQL as a database, Let’s create a db into mysql, the db name is 'test' and creating employee table into this db. We will run below sql query to create employee table –


CREATE TABLE IF NOT EXISTS `employee` (
`id` int(11) NOT NULL COMMENT 'primary key',
  `employee_name` varchar(255) NOT NULL COMMENT 'employee name',
  `employee_salary` double NOT NULL COMMENT 'employee salary',
  `employee_age` int(11) NOT NULL COMMENT 'employee age'
) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=latin1 COMMENT='datatable demo table';

--
-- Dumping data for table `employee`
--

INSERT INTO `employee` (`id`, `employee_name`, `employee_salary`, `employee_age`) VALUES
(2, 'Garrett Winters', 170750, 63),
(3, 'Ashton Cox', 86000, 66),
(4, 'Cedric Kelly', 433060, 22);

inserted some sample data to list all employee records.

Create MySQL Configuration into properties file

We will store MySQL configure parameters into properties file.Let’s create a application.properties file into resources/ folder.The spring-data-jpa is in the classpath by reading the database configuration from application.properties file.


server.port=8080
db.driver: com.mysql.jdbc.Driver
db.url: jdbc:mysql://127.0.0.1:3306/test
db.username: root
db.password: 

# Hibernate
hibernate.dialect: org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql: true
hibernate.hbm2ddl.auto: update
entitymanager.packagesToScan: com.example.restapiexample

Create Config File

We will create DbConfig.java file into /restapiexample/configs folder.This file contains data source related information.We will add below code into this file –

package com.example.restapiexample.configs;

import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * Contains database configurations.
 */
@Configuration
@EnableTransactionManagement
@ConfigurationProperties
public class DbConfig {

  // ------------------------
  // PUBLIC METHODS
  // ------------------------

  /**
   * DataSource definition for database connection. Settings are read from
   * the application.properties file (using the env object).
   */
  @Bean
  public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(env.getProperty("db.driver"));
    dataSource.setUrl(env.getProperty("db.url"));
    dataSource.setUsername(env.getProperty("db.username"));
    dataSource.setPassword(env.getProperty("db.password"));
    return dataSource;
  }

  /**
   * Declare the JPA entity manager factory.
   */
  @Bean
  public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    LocalContainerEntityManagerFactoryBean entityManagerFactory =
        new LocalContainerEntityManagerFactoryBean();
    
    entityManagerFactory.setDataSource(dataSource);
    
    // Classpath scanning of @Component, @Service, etc annotated class
    entityManagerFactory.setPackagesToScan(
        env.getProperty("entitymanager.packagesToScan"));
    
    // Vendor adapter
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    entityManagerFactory.setJpaVendorAdapter(vendorAdapter);
    
    // Hibernate properties
    Properties additionalProperties = new Properties();
    additionalProperties.put(
        "hibernate.dialect", 
        env.getProperty("hibernate.dialect"));
    additionalProperties.put(
        "hibernate.show_sql", 
        env.getProperty("hibernate.show_sql"));
    additionalProperties.put(
        "hibernate.hbm2ddl.auto", 
        env.getProperty("hibernate.hbm2ddl.auto"));
    entityManagerFactory.setJpaProperties(additionalProperties);
    
    return entityManagerFactory;
  }

  /**
   * Declare the transaction manager.
   */
  @Bean
  public JpaTransactionManager transactionManager() {
    JpaTransactionManager transactionManager = 
        new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(
        entityManagerFactory.getObject());
    return transactionManager;
  }
  
  /**
   * PersistenceExceptionTranslationPostProcessor is a bean post processor
   * which adds an advisor to any bean annotated with Repository so that any
   * platform-specific exceptions are caught and then rethrown as one
   * Spring's unchecked data access exceptions (i.e. a subclass of 
   * DataAccessException).
   */
  @Bean
  public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
    return new PersistenceExceptionTranslationPostProcessor();
  }


  // ------------------------
  // PRIVATE FIELDS
  // ------------------------
  
  @Autowired
  private Environment env;

  @Autowired
  private DataSource dataSource;

  @Autowired
  private LocalContainerEntityManagerFactoryBean entityManagerFactory;


} // class DatabaseConfig

We have imported mysql databse related information from properties file and use here.

Create Model File in Spring Boot Application

We will create employee model class into /models folder.Let’s create Employee.java file into models folder.

package com.example.restapiexample.models;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

@Entity
@Table(name = "employee")
public class Employee {
	
	  // ------------------------
	  // PRIVATE FIELDS
	  // ------------------------
	  
	  @Id
	  @GeneratedValue(strategy = GenerationType.IDENTITY)
	  private int id;
	  
	  @NotNull
	  private String employee_name;
	  
	  @NotNull
	  private int employee_salary;
	  
	  @NotNull
	  private int employee_age;
	  
	  public Employee() { }
	  
	  public Employee(int id) { 
	    this.id = id;
	  }

	  public Employee(String employee_name, int employee_salary, int employee_age) {
	    this.employee_name = employee_name;
	    this.employee_salary = employee_salary;
	    this.employee_age = employee_age;
	  }
	  public String getName() {
		  return employee_name;
	  }
	  public int getSalary() {
		  return employee_salary;
	  }
	  public int getAge() {
		  return employee_age;
	  }
	  public void setAge(int age) {
		  this.employee_age = age;
	  }
	  public void setName(String name) {
		  this.employee_name = name;
	  }
	  public void setSalary(int salary) {
		  this.employee_salary = salary;
	  }
	  public void setId(int value) {
	    this.id = value;
	  }
	  public int getId() {
	    return id;
	  }
	
}

Create DAO Layer Into Spring Boot Appplication

Let’s create dao layer for spring employee model. We will create EmployeeDao.java file into models/ folder and added below code into this file –

package com.example.restapiexample.models;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;

import org.springframework.stereotype.Repository;

import com.example.restapiexample.models.Employee;

@Repository
@Transactional
public class EmployeeDao {
	@PersistenceContext
	  private EntityManager entityManager;
	  /**
	   * Return all the employee stored in the database.
	   */
	  @SuppressWarnings("unchecked")
	  public List getAll() {
	    return entityManager.createQuery("from Employee").getResultList();
	  }
	  
	  public Employee getById(int id) {
		  return entityManager.find(Employee.class, id);
	  }
	  
	  /**
	   * Save the employee in the database.
	   */
	  public Employee create(Employee emp) {
	    entityManager.persist(emp);
	    int id = emp.getId();
	    return entityManager.find(Employee.class, id);
	  }
	  /**
	   * delete the employee in the database.
	   */
	  public Boolean delete(Employee emp) {
		  if (entityManager.contains(emp))
			  entityManager.remove(emp);
		  else
			  entityManager.remove(entityManager.merge(emp));
		  
		  return true;
	  }
}

Create Controller Class into Spring Boot

We have created model class, DAO layer and configure JPA using dbconfig file, So now lets create controller file that will handle all rest end point and return response.

package com.example.restapiexample.controllers;

import com.example.restapiexample.models.Employee;
import com.example.restapiexample.models.EmployeeDao;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class EmployeeController {
	@Autowired
	EmployeeDao employeeDao;
	
	@RequestMapping("/getall")
	@ResponseBody
	public List getAll() {
		return employeeDao.getAll();
	}
	
	@RequestMapping(value = "/get/{id}", method = RequestMethod.GET, consumes="application/json")
	@ResponseBody
	public ResponseEntity getById(@PathVariable("id") int id) {
		Employee emp = null;
		HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        headers.add("Responded", "EmployeeController");
        
		try {
			emp = employeeDao.getById(id);
		} catch(Exception ex) {
			 System.out.println("Employee not found" + ex.getMessage());
			 return ResponseEntity.accepted().headers(headers).body(emp);
		}
		
		return ResponseEntity.ok().headers(headers).body(emp);
	}
	
	@RequestMapping(value = "/create", method = RequestMethod.POST, consumes="application/json")
	@ResponseBody
	public ResponseEntity create(@RequestBody Employee postdata) {
		Employee emp = null;
		HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        headers.add("Responded", "EmployeeController");
        
		try {
			emp = employeeDao.create(postdata);
		} catch(Exception ex) {
			 System.out.println("Employee not found" + ex.getMessage());
			 return ResponseEntity.ok().headers(headers).body(emp);
		}
		
		return ResponseEntity.ok().headers(headers).body(emp);
	}
	
	@RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE, consumes="application/json")
	@ResponseBody
	public String delete(@PathVariable("id") int id) {
		boolean isDeleted = false;
		HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        headers.add("Responded", "EmployeeController");
        
		try {
			Employee emp = new Employee(id);
			isDeleted = employeeDao.delete(emp);
		} catch(Exception ex) {
			 System.out.println("Employee not found to delete" + ex.getMessage());
			 return "Error deleting the Employee: " + ex.toString();
		}
		
		if(isDeleted) {
			return "Employee succesfully deleted!";
		}
		return "Error! Employee deleted!";
	}
}

Created three calls, /getall is responsible to get all employee records, /create will use to post data and create new record, /get/{id} is use to get a single employee record and /delete/{id} rest end point use to delete record.

Get All Records Using Postman

Get A Single Record Using Postman

get single records api

Create A record Using Postman

create record spring boot api

Delete A record Using Postman

spring boot delete record api