CREATE TABLE `product` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(45) NOT NULL, `price` float NOT NULL, PRIMARY KEY (`id`) );This is a simple table containing just 3 columns: id, name and price.
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.2.RELEASE</version> </parent> <dependencies> <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> </dependencies> <properties> <java.version>1.8</java.version> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
spring.jpa.hibernate.ddl-auto=none spring.datasource.url=jdbc:mysql://localhost:3306/mydb spring.datasource.username=root spring.datasource.password=passwordRemember to update url, username and password according to your MySQL database server.
package net.codejava; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @Entity public class Product { private Integer id; private String name; private float price; public Product() { } public Product(Integer id, String name, float price) { this.id = id; this.name = name; this.price = price; } @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public Integer getId() { return id; } // other getters and setters... }This is a simple domain model class, with class name and field names are identical to table name and column names in the database – so we can use the minimum number of JPA annotations.
package net.codejava; import org.springframework.data.jpa.repository.JpaRepository; public interface ProductRepository extends JpaRepository<Product, Integer> { }Then Spring Data JPA will generate implementation code for the most common CRUD operations – we don’t have to write a single query.
package net.codejava; import java.util.List; import javax.transaction.Transactional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service @Transactional public class ProductService { @Autowired private ProductRepository repo; public List<Product> listAll() { return repo.findAll(); } public void save(Product product) { repo.save(product); } public Product get(Integer id) { return repo.findById(id).get(); } public void delete(Integer id) { repo.deleteById(id); } }As you can see, this business/service class simply forwards the calls to an implementation of the ProductRepository interface. In addition, all the methods are executed in transactions because this class is marked with the @Transactional annotation.
Spring Boot REST APIs Ultimate Course
Learn Hands-on REST API Development with Spring Boot: Design, Implement, Document, Secure, Test, Consume RESTful APIs
package net.codejava; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }This class will start embedded Tomcat server hosting our Spring Boot web application.
package net.codejava; import java.util.*; import org.springframework.beans.factory.annotation.*; import org.springframework.http.*; import org.springframework.web.bind.annotation.*; @RestController public class ProductController { @Autowired private ProductService service; // RESTful API methods for Retrieval operations // RESTful API method for Create operation // RESTful API method for Update operation // RESTful API method for Delete operation }The @RestController annotation enables the handler methods in this controller to be exposed as RESTful APIs, e.g. reading JSON data from the request and including JSON data to the response. And this REST controller still takes advantages of Spring’s dependency injection (an instance of ProductService is autowired).Let’s see how to implement RESTful API for each CRUD operation in the next sections.
@GetMapping("/products") public List<Product> list() { return service.listAll(); }Now we can run the Application class and test. With Eclipse, you can see the Spring Boot logo appears in the Console view as shown in the following screenshot:From the logging information, you can see Tomcat, Spring Data JPA and Hibernate are started. And the server listens on port 8080 by default.Use MySQL Workbench to insert the first row into the product table (name: iPhone X, price: 999.98). And type the following curl command:
curl http://localhost:8080/productsThen you can see the server’s response like this:
[{"id":1,"name":"iPhone X","price":999.98}]This is the JSON representation of a List of Product objects. Spring uses Jackson JSON library to serialize Java objects to JSON and vice-versa, automatically.Next, let’s implement the second method for a RESTful API that allows the clients to get information about a specific product based on ID, like this:
@GetMapping("/products/{id}") public ResponseEntity<Product> get(@PathVariable Integer id) { try { Product product = service.get(id); return new ResponseEntity<Product>(product, HttpStatus.OK); } catch (NoSuchElementException e) { return new ResponseEntity<Product>(HttpStatus.NOT_FOUND); } }In this method, if a product is found for the given ID, the server sends a response that includes JSON representation of the Product object with HTTP status OK (200). Else if no product is found, it returns HTTP status Not Found (404).Type the following curl command to test:
curl http://localhost:8080/products/1Response from the server:
[{"id":1,"name":"iPhone X","price":999.98}]Try to test with a non-exist ID:
curl –v http://localhost:8080/products/10You will see HTTP 404 status in the verbose output.NOTE: In case of no items in the list (the returned list is empty) the API should return HTTP status 204 No Content. For details, check this article: Spring Boot REST API CRUD with HATEOAS Tutorial
@PostMapping("/products") public void add(@RequestBody Product product) { service.save(product); }Using @PostMapping annotation, this method handles only HTTP POST request. And type the following command to test:
curl -X POST -H "Content-Type: application/json" -d "{\"name\":\"XBox 360\",\"price\":299.99}" http://localhost:8080/productsCheck the database in MySQL Workbench and you should see a second row was inserted.For validating data in the request's body, refer to this article: Spring Boot REST API Request Validation ExamplesNOTE: if the creation operation is successful, the API should return HTTP status 201 Created. For details, check this article: Spring Boot REST API CRUD with HATEOAS Tutorial
@PutMapping("/products/{id}") public ResponseEntity<?> update(@RequestBody Product product, @PathVariable Integer id) { try { Product existProduct = service.get(id); service.save(product); return new ResponseEntity<>(HttpStatus.OK); } catch (NoSuchElementException e) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } }The @PutMapping annotation specifies that this method accepts only HTTP PUT request. If a product found with the given ID, it is updated and the server returns HTTP status OK. If no product found, the HTTP status Not Found (404) is returned.Using curl, type the following command to test updating the product with ID 1:
curl -X PUT -H "Content-Type: application/json" -d "{\"id\":1,\"name\":\"iPad\",\"price\":888}" http://localhost:8080/products/1Type this command to check the update:
curl http://localhost:8080/products
@DeleteMapping("/products/{id}") public void delete(@PathVariable Integer id) { service.delete(id); }And type the following command to test deleting the product with ID 1:
curl -X DELETE http://localhost:8080/products/1You should see the row ID 1 removed from the database.NOTE: if the delete operation is successful, the API should return HTTP status code 204 No Content. For details, check this article: Spring Boot REST API CRUD with HATEOAS TutorialCongratulations, you have completed the Spring Boot tutorial about RESTful APIs for CRUD operations with MySQL database. For your reference, you can download the sample project attached below, or clone the sample project code from this GitHub repo.You can also watch the video version of this tutorial below: What's Next? I recommend you follow the next one: Spring Boot REST API CRUD with HATEOAS Tutorial