Spring Boot + MySQL で CRUDアプリを作る

---
参考記事は[こちら]
(https://www.codejava.net/frameworks/spring-boot/spring-boot-crud-example-with-spring-mvc-spring-data-jpa-thymeleaf-hibernate-mysql)

---
では早速

## 1.MySQLの準備
```
$ mysql -u root -p 
mysql> create database productdb;
mysql> use productdb;
mysql> CREATE TABLE `product` (
    ->   `id` int(11) NOT NULL AUTO_INCREMENT,
    ->   `name` varchar(45) NOT NULL,
    ->   `brand` varchar(45) NOT NULL,
    ->   `madein` varchar(45) NOT NULL,
    ->   `price` float NOT NULL,
    ->   PRIMARY KEY (`id`)
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
```
ユーザーも追加

```
mysql> use mysql;
mysql> create user 'productuser'@'localhost' identified by 'productpass';
mysql> grant all on productdb.* to productuser@localhost;
mysql> exit
```

ユーザーの確認とデータの投入

```
$ mysql -u productuser -pproductpass         
mysql> use productdb;
mysql> insert into product (name, brand, madein, price) values
    -> ('Glaxy S10 Plus', 'Samsung Corp', 'Korea', 901.0),
    -> ('MacBook Air', 'Apple', 'China', 1230.0),
    -> ('Mazda 3', 'Mazda', 'Japan', 27900.0);

mysql> select * from product;
+----+----------------+--------------+--------+-------+
| id | name           | brand        | madein | price |
+----+----------------+--------------+--------+-------+
|  1 | Glaxy S10 Plus | Samsung Corp | Korea  |   901 |
|  2 | MacBook Air    | Apple        | China  |  1230 |
|  3 | Mazda 3        | Mazda        | Japan  | 27900 |
+----+----------------+--------------+--------+-------+
3 rows in set (0.01 sec)

mysql> exit
```

## 2.プロジェクト作成
[Spring Initializr](https://start.spring.io/)にてプロジェクトを作成
<img width="1288" alt="product-manager.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665074/7fa277e0-8814-1cbd-cd6c-c4a1291898f1.png">
[*GENERATE ⌘ + ↩︎* ]で、ZIPファイルが生成される
ZIPファイルを解凍すると、プロジェクトが作成される

## 3.データベースと接続する設定
src/main/resources/application.propertiesにデータベース接続の設定を記入

```ruby:application.properties
spring.jpa.database=MYSQL
spring.datasource.platform=mysql
spring.datasource.url=jdbc:mysql://localhost:3306/productdb?setAutoCommit=false&useSSL=false
spring.datasource.username=productuser
spring.datasource.password=productpass
spring.jpa.hibernate.ddl-auto=none
logging.level.root=WARN

```

## 4.Entityの作成
```ruby:Product.java
package com.example.productmanager.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import lombok.Data;

@Data
@Entity
public class Product {
	private Long id;
    private String name;
    private String brand;
    private String madein;
    private float price;
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long getId() {
        return id;
    }
}
```

## 5.Repositoryの作成
```ruby:ProductRepository.java
package com.example.productmanager.repository;

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

import com.example.productmanager.entity.Product;

public interface ProductRepository extends JpaRepository<Product, Long> {

}
```

## 6.Serviceの作成
```ruby:ProductService.java
package com.example.productmanager.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.example.productmanager.entity.Product;
import com.example.productmanager.repository.ProductRepository;

@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(long id) {
        return repo.findById(id).get();
    }
     
    public void delete(long id) {
        repo.deleteById(id);
    }
}
```
## 7.Controllerの作成
```ruby:AppController.java
package com.example.productmanager.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import com.example.productmanager.entity.Product;
import com.example.productmanager.service.ProductService;


@Controller
public class AppController {
	@Autowired
    private ProductService service;
	
	@RequestMapping("/")
	public String viewHomePage(Model model) {
	    List<Product> listProducts = service.listAll();
	    model.addAttribute("listProducts", listProducts);
	     
	    return "index";
	}
	
	@RequestMapping("/new")
	public String showNewProductPage(Model model) {
	    Product product = new Product();
	    model.addAttribute("product", product);
	     
	    return "new_product";
	}
	
	@RequestMapping(value = "/save", method = RequestMethod.POST)
	public String saveProduct(@ModelAttribute("product") Product product) {
	    service.save(product);
	     
	    return "redirect:/";
	}
	
	@RequestMapping("/edit/{id}")
	public ModelAndView showEditProductPage(@PathVariable(name = "id") int id) {
	    ModelAndView mav = new ModelAndView("edit_product");
	    Product product = service.get(id);
	    mav.addObject("product", product);
	     
	    return mav;
	}
	
	@RequestMapping("/delete/{id}")
	public String deleteProduct(@PathVariable(name = "id") int id) {
	    service.delete(id);
	    return "redirect:/";       
	}
}
```

## 8.Viewの作成
#### src/resources/templates/index.html

```ruby:index.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8"/>
<title>Product Manager</title>
</head>
<body>
<div align="center">
    <h1>Product List</h1>
    <a href="/new">Create New Product</a>
    <br/><br/>
    <table border="1" cellpadding="10">
        <thead>
            <tr>
                <th>Product ID</th>
                <th>Name</th>
                <th>Brand</th>
                <th>Made In</th>
                <th>Price</th>
                <th>Actions</th>
            </tr>
        </thead>
        <tbody>
            <tr th:each="product : ${listProducts}">
                <td th:text="${product.id}">Product ID</td>
                <td th:text="${product.name}">Name</td>
                <td th:text="${product.brand}">Brand</td>
                <td th:text="${product.madein}">Made in</td>
                <td th:text="${product.price}">Price</td>
                <td>
                    <a th:href="@{'/edit/' + ${product.id}}">Edit</a>
                    &nbsp;&nbsp;&nbsp;
                    <a th:href="@{'/delete/' + ${product.id}}">Delete</a>
                </td>
            </tr>
        </tbody>
    </table>
</div>   
</body>
</html>
```

#### src/resources/templates/new_product.html

```ruby:new_product.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8" />
<title>Create New Product</title>
</head>
<body>
    <div align="center">
        <h1>Create New Product</h1>
        <br />
        <form action="#" th:action="@{/save}" th:object="${product}"
            method="post">
 
            <table border="0" cellpadding="10">
                <tr>
                    <td>Product Name:</td>
                    <td><input type="text" th:field="*{name}" /></td>
                </tr>
                <tr>
                    <td>Brand:</td>
                    <td><input type="text" th:field="*{brand}" /></td>
                </tr>
                <tr>
                    <td>Made In:</td>
                    <td><input type="text" th:field="*{madein}" /></td>
                </tr>
                <tr>
                    <td>Price:</td>
                    <td><input type="text" th:field="*{price}" /></td>
                </tr>                            
                <tr>
                    <td colspan="2"><button type="submit">Save</button> </td>
                </tr>
            </table>
        </form>
    </div>
</body>
</html>
```

#### src/resources/templates/edit_product.html

```ruby:edit_product.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8" />
<title>Edit Product</title>
</head>
<body>
    <div align="center">
        <h1>Edit Product</h1>
        <br />
        <form action="#" th:action="@{/save}" th:object="${product}"
            method="post">
 
            <table border="0" cellpadding="10">
                <tr>             
                    <td>Product ID:</td>
                    <td>
                        <input type="text" th:field="*{id}" readonly="readonly" />
                    </td>
                </tr>        
                <tr>             
                    <td>Product Name:</td>
                    <td>
                        <input type="text" th:field="*{name}" />
                    </td>
                </tr>
                <tr>
                    <td>Brand:</td>
                    <td><input type="text" th:field="*{brand}" /></td>
                </tr>
                <tr>
                    <td>Made In:</td>
                    <td><input type="text" th:field="*{madein}" /></td>
                </tr>
                <tr>
                    <td>Price:</td>
                    <td><input type="text" th:field="*{price}" /></td>
                </tr>                            
                <tr>
                    <td colspan="2"><button type="submit">Save</button> </td>
                </tr>
            </table>
        </form>
    </div>
</body>
</html>
```

## 9.Spring Boot アプリケーションの実行

Spring Boot アプリケーションの実行後、[localhost:8080](http://localhost:8080/)を確認
<img width="853" alt=":.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665074/6dcbe161-e9bb-d0d7-09be-69f80fc84161.png">
---
<img width="853" alt="create.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665074/e91ed73f-1522-b077-1a53-999721d4d91c.png">
---
<img width="853" alt="edit.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665074/2e236cbb-388e-15f2-1bf5-5986b9c6919b.png">

---

ありがとうございました







---