- vừa được xem lúc

Tạo Rest API với spring boot + mysql + jpa repository

0 0 10

Người đăng: Tran Gia Nhuan

Theo Viblo Asia

Giới thiệu

Spring Boot là một dự án khá nổi bật trong hệ sinh thái Spring Framework. Nếu như trước đây, công đoạn khởi tạo một dự án Spring khá vất vả từ việc khai báo các dependency trong file pom.xml cho đến cấu hình bằng XML hoặc annotation phức tạp, tạo server cấu hình spring mvc, thì giờ đây với Spring Boot, chúng ta có thể tạo dự án Spring một cách nhanh chóng và cấu hình cũng đơn giản hơn. Dưới đây là một số tính năng nổi bật của Spring Boot:

  • Tạo các ứng dụng Spring độc lập
  • Nhúng trực tiếp Tomcat, Jetty hoặc Undertow (không cần phải deploy ra file WAR)
  • Các starter dependency giúp việc cấu hình Maven đơn giản hơn
  • Tự động cấu hình Spring khi cần thiết
  • Không sinh code cấu hình và không yêu cầu phải cấu hình bằng XML ... Sau đây mình sẽ hướng dẫn tạo 1 project Rest CRUD đơn giản với eclipse

Tạo dự án

New -> Project và điền thông tin cấu hình sau, thay đổi theo ý bạn

Service URL http://start.spring.io
Group : com.example
Artifact : easy-notes
Name : demo
Description : Rest API Demo
Package Name : com.example.demo
Packaging : jar ( default value)
Java Version : 1.8 (Default)
Dependencies : Web, JPA, MySQL,

ta sẽ tạo cấu trúc dự án như thế này

src/main/java
----com.example.demo
--------DemoApplication.java
----com.example.demo.api
--------RestApiController.java
----com.example.demo.model
--------Contact.java
----com.example.demo.service
--------ContactService.java

đây là nội dùng file pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demo</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.M6</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </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> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </repository> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </pluginRepository> <pluginRepository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> </pluginRepositories> </project> 

ta có thể thêm thư viện vào thông qua các dependency, spring boot sẽ tự động down và cấu hình cần thiết cho các dependency

DemoApplication

đây là điểm chính của ứng dụng spring boot

package com.example.demo; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication(scanBasePackages={"com.example.demo"})
public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }
} 

Annotation @SpringBootApplication là sự kết hợp giữa 3 annotation khác của Spring bao gồm: @SpringBootConfiguration, @ComponentScan, @EnableAutoConfiguration trong đó annotation @EnableAutoConfiguration là quan trọng nhất. Với @EnableAutoConfiguration annotation, Spring Boot sẽ tự động cấu hình cho ứng dụng của chúng ta dựa vào classpath, các annotations và các thông tin cấu hình mà chúng ta định nghĩa. Tất cả các annotation này sẽ giúp cho Spring Boot có thể tự động cấu hình cho ứng dụng của chúng ta một cách phù hợp và chúng ta không cần phải quan tâm nhiều đến việc cấu hình.

Tạo database và cấu hình kết nối mysql

CREATE TABLE `contact` ( `name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL, `age` int(3) NOT NULL, `dob` date NOT NULL, `email` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL, `id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `contact` ADD PRIMARY KEY (`id`);
ALTER TABLE `contact` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;COMMIT; INSERT INTO `contact` (`name`, `age`, `dob`, `email`, `id`) VALUES
('Nguyễn văn B', 22, '2017-11-15', '_@.com', 2),
('Nguyễn A', 22, '2017-11-01', '_@.com', 3),
('Nguyễn C', 23, '1997-11-01', '_@.com', 4),
('Test', 25, '1990-11-01', '_@.com', 5);

config

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=

Chúng ta cấu hình kết nối với database trong file application.properties nhớ thay đổi username, password, database cho phù hợp

Tạo Model

package com.example.demo.model; import java.io.Serializable;
import java.util.Date; import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @Entity
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Contact implements Serializable { /** * */ private static final long serialVersionUID = 1L; private String name; private Date dob; private int age; private String email; @Id @GeneratedValue(strategy=GenerationType.AUTO) private long id; public Contact(){ id=0; } public Contact(int id,String name, int age, Date dob, String email) { this.id =id; this.name =name; this.age =age; this.dob =dob; this.email =email; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getDob() { return dob; } public void setDob(Date dob) { this.dob = dob; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public long getId() { return id; } public void setId(long id) { this.id = id; } } 

các model sẽ phải dùng annotation @Entity Ta có thể dùng các annnotation khác thiết lập: @Table(name = "nametable") trên model để thay đổi tên table muốn mapping @ID : xác định khóa chính @GeneratedValue : tự động tăng @NotBlank :không được null hoặc rỗng @Column(nullable = false, updatable = false) cấu hình column như khai báo @Temporal(TemporalType.TIMESTAMP) chuyển đổi giá trị data từ java sang database cho hợp lí @JsonIgnoreProperties đây là 1 annotaion của jackson . Spring Boot sử dụng Jackson for Serializing and Deserializing đối tượng java từ JSON. ... để trên các thuộc tính của model ,để cấu hình tương ứng cho từng annotation

Tạo service sử dụng JpaRepository để truy cập dữ liệu từ database

package com.example.demo.service; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository; import com.example.demo.model.Contact; @Repository
public interface ContactService extends JpaRepository<Contact, Long>{ //todo
} 

Spring Data JPA đã làm mọi việc cho chúng ta. JpaRepository interface đã định nghĩa các method cho các hoạt đông CRUD trên entity. Việc của chúng ta là extend JpaRepository , không cần phải implement lại các methods Vạ chúng ta có thể sử dụng các function như save(), getOne(), findAll(), count(), delete() ...

Tạo controller

package com.example.demo.api; import java.util.List; import javax.validation.Valid; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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.RestController; import com.example.demo.model.Contact;
import com.example.demo.service.ContactService; @RestController
@RequestMapping("/api")
public class RestApiController { public static Logger logger = LoggerFactory.getLogger(RestApiController.class); @Autowired ContactService contactService; @RequestMapping(value = "/contact/", method = RequestMethod.GET) public ResponseEntity<List<Contact>> listAllContact(){ List<Contact> listContact= contactService.findAll(); if(listContact.isEmpty()) { return new ResponseEntity(HttpStatus.NO_CONTENT); } return new ResponseEntity<List<Contact>>(listContact, HttpStatus.OK); } @RequestMapping(value = "/contact/{id}", method = RequestMethod.GET) public Contact findContact(@PathVariable("id") long id) { Contact contact= contactService.getOne(id); if(contact == null) { ResponseEntity.notFound().build(); } return contact; } @RequestMapping(value = "/contact/", method = RequestMethod.POST) public Contact saveContact(@Valid @RequestBody Contact contact) { return contactService.save(contact); } @RequestMapping(value = "/contact/", method = RequestMethod.PUT) public ResponseEntity<Contact> updateContact(@PathVariable(value = "id") Long contactId, @Valid @RequestBody Contact contactForm) { Contact contact = contactService.getOne(contactId); if(contact == null) { return ResponseEntity.notFound().build(); } contact.setName(contactForm.getName()); contact.setAge(contactForm.getAge()); Contact updatedContact = contactService.save(contact); return ResponseEntity.ok(updatedContact); } @RequestMapping(value = "/contact/{id}", method = RequestMethod.DELETE) public ResponseEntity<Contact> deleteContact(@PathVariable(value = "id") Long id) { Contact contact = contactService.getOne(id); if(contact == null) { return ResponseEntity.notFound().build(); } contactService.delete(contact); return ResponseEntity.ok().build(); }
} 

@RestController annotation là sự kết hợp giữa @Controller@ResponseBody annotations. @RequestMapping("/api") để khai báo các url của các api trong controller này sẽ bắt đầu với '/api'

lấy tất cả liên hệ

@RequestMapping(value = "/contact/", method = RequestMethod.GET) public ResponseEntity<List<Contact>> listAllContact(){ List<Contact> listContact= contactService.findAll(); if(listContact.isEmpty()) { return new ResponseEntity(HttpStatus.NO_CONTENT); } //return ResponseEntity<List<Contact>>(listContact, HttpStatus.OK); return new ResponseEntity<List<Contact>>(listContact, HttpStatus.OK); }

ở đây nó sẽ gọi method findAll() của JpaRepository trả về toàn bộ danh sách liên hệ có trong database method: khai báo phương thức khi call url, GET, PUT, PATCH, POST,....

tạo mới liên hệ

@RequestMapping(value = "/contact/", method = RequestMethod.POST) public Contact saveContact(@Valid @RequestBody Contact contact) { return contactService.save(contact); }

@RequestBody tương ứng với body của request @Valid để đảm bảo request body là hợp lệ nếu ta dùng các annotation validation như @NotBlank...

lấy một liên hệ

@RequestMapping(value = "/contact/{id}", method = RequestMethod.GET) public Contact findContact(@PathVariable("id") long id) { Contact contact= contactService.getOne(id); if(contact == null) { ResponseEntity.notFound().build(); } return contact; }

@PathVariable mapping biến ở đường dẫn với biến tham số gọi method getOne() để lấy dữ liệu thông qua đối số

update liên hệ

@RequestMapping(value = "/contact/", method = RequestMethod.PUT) public ResponseEntity<Contact> updateContact(@PathVariable(value = "id") Long contactId, @Valid @RequestBody Contact contactForm) { Contact contact = contactService.getOne(contactId); if(contact == null) { return ResponseEntity.notFound().build(); } contact.setName(contactForm.getName()); contact.setAge(contactForm.getAge()); Contact updatedContact = contactService.save(contact); return ResponseEntity.ok(updatedContact); }

Xóa liên hệ

@RequestMapping(value = "/contact/{id}", method = RequestMethod.DELETE) public ResponseEntity<Contact> deleteContact(@PathVariable(value = "id") Long id) { Contact contact = contactService.getOne(id); if(contact == null) { return ResponseEntity.notFound().build(); } contactService.delete(contact); return ResponseEntity.ok().build(); }

Chạy ứng dụng

có thể chạy ứng dụng bằng 2 cách

Click chuột phải vào Project -> Run as -> Spring Boot App

or vào thư mục gốc projcet chạy bằng command line

mvnw spring-boot:run

Test

Ta dùng Postman để test lấy 1 liên hệ http://localhost:8080/api/contact/{id} method GET lấy tất cả liên hệ http://localhost:8080/api/contact/ method GET tạo mới 1 liên hệ http://localhost:8080/api/contact/ method POST update 1 liên hệ http://localhost:8080/api/contact/{id} method PUT

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 525

- vừa được xem lúc

Cài đặt WSL / WSL2 trên Windows 10 để code như trên Ubuntu

Sau vài ba năm mình chuyển qua code trên Ubuntu thì thật không thể phủ nhận rằng mình đã yêu em nó. Cá nhân mình sử dụng Ubuntu để code web thì thật là tuyệt vời.

0 0 397

- vừa được xem lúc

Đặt tên commit message sao cho "tình nghĩa anh em chắc chắn bền lâu"????

. Lời mở đầu. .

1 1 738

- vừa được xem lúc

Tìm hiểu về Resource Controller trong Laravel

Giới thiệu. Trong laravel, việc sử dụng các route post, get, group để gọi đến 1 action của Controller đã là quá quen đối với các bạn sử dụng framework này.

0 0 358

- vừa được xem lúc

Phân quyền đơn giản với package Laravel permission

Như các bạn đã biết, phân quyền trong một ứng dụng là một phần không thể thiếu trong việc phát triển phần mềm, dù đó là ứng dụng web hay là mobile. Vậy nên, hôm nay mình sẽ giới thiệu một package có thể giúp các bạn phân quyền nhanh và đơn giản trong một website được viết bằng PHP với framework là L

0 0 450

- vừa được xem lúc

Bạn đã biết các tips này khi làm việc với chuỗi trong JavaScript chưa ?

Hi xin chào các bạn, tiếp tục chuỗi chủ đề về cái thằng JavaScript này, hôm nay mình sẽ giới thiệu cho các bạn một số thủ thuật hay ho khi làm việc với chuỗi trong JavaScript có thể bạn đã hoặc chưa từng dùng. Cụ thể như nào thì hãy cùng mình tìm hiểu trong bài viết này nhé (go).

0 0 433