REST API :
REST : Representational state transfer
API : Application Programming Interface
-> Lightweight approach for communicating between application. It is language independent.
-> Commonly used data format is XML and JSON
Benefits of using spring boot
i) Embedded HTTP server
ii) Create stand-alone Spring applications
iii)Save time on on preparing and configuring the environment
iv) It provides flexible XML configurations, robust batch processing, database transactions, easy workflow, along with a wide variety of tools for development.
CRUD stands for Create, Read, Update and Delete, which refers to the following four operations
HTTP Method | CRUD Operation |
---|---|
POST | Create a new entity |
GET | Read a list of entities or single entity |
PUT/PATCH | Update an existing entity |
DELETE | Delete an existing entity |
Tools and technologies used
- Java (Version 8)
- Spring Boot
- Hibernate
- Maven
- MySql
- Eclipse
- Apache Tomcat
- MySql workbench
Project Structure
How to create spring boot project
Database Details
Create a database
employee.sql
CREATE DATABASE IF NOT EXISTS `employee_cruddemo`;
USE `employee_cruddemo`;
--
-- Table structure for table `employee`
--
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`first_name` varchar(45) DEFAULT NULL,
`last_name` varchar(45) DEFAULT NULL,
`email` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
--
-- Data for table `employee`
--
INSERT INTO `employee` VALUES
(1,'Sachin','Kumar','[email protected]'),
(2,'Mohan','Yadav','[email protected]'),
(3,'Avani','Patel','[email protected]'),
(4,'Mayank','Gupta','[email protected]'),
(5,'Amar','Singh','[email protected]');
Properties file
Create application.properties in src/main/resources
application.properties
#
# JDBC properties
#
spring.datasource.url=jdbc:mysql://localhost:3306/employee_cruddemo?useSSL=false&serverTimezone=UTC
spring.datasource.username=dbemployee
spring.datasource.password=dbemployee
Jar Dependency
Add following dependency in pom.xml
<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.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Entity Class
Create entity class in com.codebaji.springboot.web.springboothibernaterestcruddemo.entity
Employee.java
package com.codebaji.springboot.web.springboothibernaterestcruddemo.entity;
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="employee")
public class Employee {
// define fields
@Id
@Column(name="id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
@Column(name="email")
private String email;
// define constructors
public Employee() {
}
public Employee(String firstName, String lastName, String email) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
// define getter/setter
public int getId() {
return id;
}
public void setId(int 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;
}
// define tostring
@Override
public String toString() {
return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + "]";
}
}
Controller Class
Create Controller class in com.codebaji.springboot.web.springboothibernaterestcruddemo.rest
EmployeeRestController.java
package com.codebaji.springboot.web.springboothibernaterestcruddemo.rest;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
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.codebaji.springboot.web.springboothibernaterestcruddemo.entity.Employee;
import com.codebaji.springboot.web.springboothibernaterestcruddemo.service.EmployeeService;
@RestController
@RequestMapping("/api")
public class EmployeeRestController {
@Autowired
private EmployeeService employeeService;
// expose "/employees" and return list of employees
@GetMapping("/employees")
public List<Employee> getAll(){
return employeeService.findAll();
}
// add mapping for GET /employees/{employeeId}
@GetMapping("/employees/{employeeId}")
public Employee findById(@PathVariable int employeeId) {
Employee theEmployee = employeeService.findById(employeeId);
if(theEmployee == null) {
throw new RuntimeException("Employee id not found - " + employeeId);
}
return theEmployee;
}
// add mapping for POST /employees - add new employee
@PostMapping("/employees")
public Employee addEmployee(@RequestBody Employee theEmployee) {
// also just in case they pass an id in JSON ... set id to 0
// this is to force a save of new item ... instead of update
theEmployee.setId(0);
employeeService.save(theEmployee);
return theEmployee;
}
// add mapping for PUT /employees - update existing employee
@PutMapping("/employees")
public Employee updateEmployee(@RequestBody Employee theEmployee) {
employeeService.save(theEmployee);
return theEmployee;
}
// add mapping for DELETE /employees/{employeeId} - delete employee
@DeleteMapping("/employees/{employeeId}")
public String deleteEmployee(@PathVariable int employeeId) {
Employee tempEmployee = employeeService.findById(employeeId);
// throw exception if null
if (tempEmployee == null) {
throw new RuntimeException("Employee id not found - " + employeeId);
}
employeeService.deleteById(employeeId);
return "Deleted employee id - " + employeeId;
}
}
Data Access Object (DAO) class
Create DAO class in com.codebaji.springboot.web.springboothibernaterestcruddemo.dao
EmployeeDAO.java
package com.codebaji.springboot.web.springboothibernaterestcruddemo.dao;
import java.util.List;
import com.codebaji.springboot.web.springboothibernaterestcruddemo.entity.Employee;
public interface EmployeeDAO {
public List<Employee> findAll();
public Employee findById(int theId);
public void save(Employee theEmployee);
public void deleteById(int theId);
}
EmployeeDAOHibernateImpl.java
package com.codebaji.springboot.web.springboothibernaterestcruddemo.dao;
import java.util.List;
import javax.persistence.EntityManager;
import org.hibernate.Session;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.codebaji.springboot.web.springboothibernaterestcruddemo.entity.Employee;
@Repository
public class EmployeeDAOHibernateImpl implements EmployeeDAO {
// define field for entitymanager
@Autowired
private EntityManager entityManager;
@Override
public List<Employee> findAll() {
// get the current hibernate session
Session currentSession = entityManager.unwrap(Session.class);
// create a query
Query<Employee> theQuery = currentSession.createQuery("from Employee", Employee.class);
// execute query and get result list
List<Employee> employees = theQuery.getResultList();
// return the results
return employees;
}
@Override
public Employee findById(int theId) {
// get the current hibernate session
Session currentSession = entityManager.unwrap(Session.class);
// get the employee
Employee theEmployee = currentSession.get(Employee.class, theId);
// return the employee
return theEmployee;
}
@Override
public void save(Employee theEmployee) {
// get the current hibernate session
Session currentSession = entityManager.unwrap(Session.class);
// save employee
currentSession.saveOrUpdate(theEmployee);
}
@Override
public void deleteById(int theId) {
// get the current hibernate session
Session currentSession = entityManager.unwrap(Session.class);
// delete object with primary key
Query theQuery = currentSession.createQuery("delete from Employee where id=:employeeId");
theQuery.setParameter("employeeId", theId);
theQuery.executeUpdate();
}
}
Service Class
Create Service class in com.codebaji.springboot.web.springboothibernaterestcruddemo.service
EmployeeService.java
package com.codebaji.springboot.web.springboothibernaterestcruddemo.service;
import java.util.List;
import com.codebaji.springboot.web.springboothibernaterestcruddemo.entity.Employee;
public interface EmployeeService {
public List<Employee> findAll();
public Employee findById(int theId);
public void save(Employee theEmployee);
public void deleteById(int theId);
}
EmployeeServiceImpl.java
package com.codebaji.springboot.web.springboothibernaterestcruddemo.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.codebaji.springboot.web.springboothibernaterestcruddemo.dao.EmployeeDAO;
import com.codebaji.springboot.web.springboothibernaterestcruddemo.entity.Employee;
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeDAO employeeDAO;
@Override
@Transactional
public List<Employee> findAll() {
return employeeDAO.findAll();
}
@Override
@Transactional
public Employee findById(int theId) {
return employeeDAO.findById(theId);
}
@Override
@Transactional
public void save(Employee theEmployee) {
employeeDAO.save(theEmployee);
}
@Override
@Transactional
public void deleteById(int theId) {
employeeDAO.deleteById(theId);
}
}
Details of annotations used in this project
- @Entity : The @Entity annotation specifies that the class is an entity and is mapped to a database table.
- @Table : The @Table annotation specifies the name of the database table to be used for mapping.
- @Id : The @Id annotation specifies the primary key of an entity.
- @Column : The Column annotation is used to specify the mapped column for a persistent property or field. If no Column annotation is specified, the default value will be applied.
- @GeneratedValue : @GeneratedValue provides for the specification of generation strategies for the values of primary keys.
- @Override : The @Override annotation indicates that the child class method is over-writing its base class method.
- @RestController : Spring RestController takes care of mapping request data to the defined request handler method. It is Extension of @Controller. Handles REST requests and responses.
- @RequestMapping : The @Entity annotation specifies that the class is an entity and is mapped to a database table. It maps HTTP request with a path to a controller method.
- @Autowired : It marks a constructor, field, or setter method to be autowired by Spring dependency injection.
- @GetMapping : It handles the HTTP GET requests matched with given URI expression. It is a shortcut for @RequestMapping(method = RequestMethod.GET).
- @PostMapping : It maps HTTP POST requests onto specific handler methods. It is a composed annotation that acts as a shortcut for @RequestMapping(method = RequestMethod.POST).
- @PutMapping : It is used for mapping HTTP PUT requests onto specific handler methods. Specifically, @PutMapping is a composed annotation that acts as a shortcut for @RequestMapping(method = RequestMethod.PUT).
- @DeleteMapping : @DeleteMapping annotation maps HTTP DELETE requests onto specific handler methods. It is a composed annotation that acts as a shortcut for @RequestMapping(method = RequestMethod.DELETE).
- @Repository : Indicates that an annotated class is a repository, which is an abstraction of data access and storage.
- @Service : It indicates that an annotated class is a service class. @Service annotation is used with classes that provide some business functionalities.
- @Transactional : It minimize(eliminate) code to manually stopping and starting transaction.
- @RequestBody : Used to access the request body as POJO. It binds POJO to a method parameter.
- @PathVariable : It indicates that a method parameter should be bound to a URI template variable.