STACKJAVA

Code ví dụ Spring Boot RESTful Webservice với MySQL (JPA)

Code ví dụ Spring Boot RESTful Webservice với MySQL (JPA)

(Xem lại: Web Service là gì?)

(Xem lại: Giới thiệu về RESTful web service.)

(Xem lại: Code ví dụ, tạo RESTful Web Service với Spring MVC)

(Xem lại: Code ví dụ Spring Boot RESTful Webservice (CRUD))

(Xem lại: Code ví dụ Spring Boot – Spring Data JPA với MySQL)

Các công nghệ sử dụng:

Tạo Database

Tạo database spring-data với table customer

CREATE DATABASE  IF NOT EXISTS `spring-data`;
CREATE TABLE `spring-data`.`customer` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) DEFAULT NULL,
  `address` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

Code ví dụ

Ở bài này mình sẽ tạo API Webservice để thêm, sửa, xóa, lấy dữ liệu từ database MySQL.

Tạo Spring Boot Project:

Cấu trúc Project

Khi tạo project Spring Boot nó sẽ tự động thêm các thư viện jackson để mapping dữ liệu trả về sang dạng JSON

File cấu hình Spring Boot

Trong file cấu hình Spring Boot ta cấu hình kết nối tới server MySQL

## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/spring-data?useSSL=false
spring.datasource.username=root
spring.datasource.password=admin1234

## ==============JPA / HIBERNATE=================
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect

Mặc định Spring Boot sẽ tự động cấu hình JPA và các bean liên quan gồm DataSourceAutoConfigurationDataSourceTransactionManagerAutoConfigurationHibernateJpaAutoConfiguration theo cấu hình trong file application.properties

File Entity

package stackjava.com.restful.entities;

import javax.persistence.*;

@Entity
@Table(name = "customer")
public class Customer {
  @Id
  @Column(name = "id")
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private int id;

  @Column(name = "name")
  private String name;

  @Column(name = "address")
  private String address;

  // getter - setter

}

File Repository

package stackjava.com.restful.repository;

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

import stackjava.com.restful.entities.Customer;

@Repository
public interface CustomerRepository extends JpaRepository<Customer, Integer> {
    
}

File Service

File service sẽ kiểm tra dữ liệu đầu vào, gọi tới repository để lấy dữ liệu và trả về cho Controller.

package stackjava.com.restful.service;

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

import stackjava.com.restful.repository.CustomerRepository;
import stackjava.com.restful.service.ServiceResult.Status;
import stackjava.com.restful.entities.Customer;

@Service
public class CustomerService {

  @Autowired
  CustomerRepository customerRepo;

  public ServiceResult findAll() {
    ServiceResult result = new ServiceResult();
    result.setData(customerRepo.findAll());
    return result;
  }

  public ServiceResult findById(int id) {
    ServiceResult result = new ServiceResult();
    Customer customer = customerRepo.findById(id).orElse(null);
    result.setData(customer);
    return result;
  }

  public ServiceResult create(Customer customer) {
    ServiceResult result = new ServiceResult();
    result.setData(customerRepo.save(customer));
    return result;
  }

  public ServiceResult update(Customer customer) {
    ServiceResult result = new ServiceResult();

    if (!customerRepo.findById(customer.getId()).isPresent()) {
      result.setStatus(Status.FAILED);
      result.setMessage("Customer Not Found");
    } else {
      result.setData(customerRepo.save(customer));
    }
    return result;
  }

  public ServiceResult delete(int id) {
    ServiceResult result = new ServiceResult();

    Customer customer = customerRepo.findById(id).orElse(null);
    if (customer == null) {
      result.setStatus(Status.FAILED);
      result.setMessage("Customer Not Found");
    } else {
      customerRepo.delete(customer);
      result.setMessage("success");
    }
    return result;
  }
}

 

Ở đây tất cả dữ liệu trả về đều là ServiceResult, thay vì trả về mỗi dữ liệu query, mình sẽ có thêm các thông tin như status, message thông báo trong trường hợp lỗi… Các bạn có thể thêm các trường khác như error_code… để phía client biết rõ lỗi gặp phải là gì, hay thêm đa ngôn ngữ vào message trả về…

package stackjava.com.restful.service;

public class ServiceResult {
  private Status status = Status.SUCCESS;
  private String message;
  private Object data;

  public enum Status {
    SUCCESS, FAILED;
  }

  // getter - setter

}

File Request

Ngoài trừ API GET, dữ liệu được truyền qua path của URL thì tất cả dữ liệu của các API DELETE, PUT, POST đều phải là dữ liệu JSON.

Ví dụ trường hợp xóa, mình cần truyền id lên thì mình sẽ tạo một class để wrap lại id đó.

package stackjava.com.restful.controller;

public class DeleteCustomerRequest {
  private int id;

  // getter - setter
}

Các trường hợp tạo, sửa Customer mình sử dụng lại class Customer.javacho nhanh. Còn trong thực tế thì các bạn nên tạo class Request riêng cho nó nhé, ví dụ lúc tạo thì không yêu cầu id, còn lúc sửa thì phải yêu cầu id.

File Controller

package stackjava.com.restful.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
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 stackjava.com.restful.service.CustomerService;
import stackjava.com.restful.service.ServiceResult;
import stackjava.com.restful.entities.Customer;

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

  @Autowired
  private CustomerService customerService;

  /* ---------------- GET ALL CUSTOMER ------------------------ */
  @GetMapping("/customers")
  public ResponseEntity<ServiceResult> findAllCustomer() {
    return new ResponseEntity<ServiceResult>(customerService.findAll(), HttpStatus.OK);
  }

  /* ---------------- GET CUSTOMER BY ID ------------------------ */
  @GetMapping("/customers/{id}")
  public ResponseEntity<ServiceResult> findById(@PathVariable int id) {
    return new ResponseEntity<ServiceResult>(customerService.findById(id), HttpStatus.OK);
  }

  /* ---------------- CREATE NEW CUSTOMER ------------------------ */
  @PostMapping("/customers")
  public ResponseEntity<ServiceResult> create(@RequestBody Customer customer) {
    return new ResponseEntity<ServiceResult>(customerService.create(customer), HttpStatus.OK);
  }
  
  /* ---------------- UPDATE CUSTOMER ------------------------ */
  @PutMapping("/customers")
  public ResponseEntity<ServiceResult> update(@RequestBody Customer customer) {
    return new ResponseEntity<ServiceResult>(customerService.update(customer), HttpStatus.OK);
  }

  @DeleteMapping("/customers")
  public ResponseEntity<ServiceResult> delete(@RequestBody DeleteCustomerRequest request) {
    return new ResponseEntity<ServiceResult>(customerService.delete(request.getId()), HttpStatus.OK);
  }

}

Demo:

Khởi động MongoDB và chạy project.

Ở đây mình dùng postman extension trên chrome để gửi các request thêm, sửa, xóa, update đối tượng customer.

Request tạo Customer:

Mình tạo 2 customer là {"name":"sena", "address":"korean"} và {"name":"kai", "address":"viet nam"}

Demo Code ví dụ Spring Boot RESTful Webservice với MySQL (JPA)

Kết quả trả về sẽ có id của đối tượng customer được tạo ra.

 

Request lấy tất cả các đối tượng Customer:

Request lấy đối tượng Customer theo id:

Request Update đối tượng Customer:

Ở đây mình sửa address của “kai” thành “usa”

Request Xóa đối tượng Customer:

Ở đây mình xóa customer “sena”

Xác nhận lại bằng request find all:

Kết quả: không còn customer “sena”, customer “kai” đã được sửa address thành “usa”

 

Okay, done!

Download code ví dụ trên tại đây.

 

References:

https://docs.spring.io/spring-data/../reference/html/

https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/