Spring Boot + PostgreSQL使ってアプリを作成してみた【CRUD App】

## 1.プロジェクトを作成する

公式：[spring initializr](https://start.spring.io/)

① ブラウザを開き、(https://start.spring.io/) を入力し、開く
② 下記を入力し、Dependenciesで下記を選択し、『GENERATE』ボタンを押す

- Project: Maven
- Language: Java
- SpringBoot: 3.1.1

- Group: com.postgresql
- Artifact: crud
- Name : crud
- Description: Demo projects for Spring Boot with Postgresql
- Package name: com.postgresql.crud

Dependencies
- Spring Boot Starter jdbc
- Spring Boot Starter Web
- Spring Boot DevTools
- boostrap
- Jquery
- Spring Data JPA
- PostgreSQL Driver

## 2.プロパティを追加する

① src/mainにwebapp/WEB-INF/jspファイルを作成する。

② resources/application.propertiesを編集する

```application.properties
server.port = 自身のポート番号

# プロパティ変更を行う
spring.mvc.view.prefix=/WEB-INF/jsp
spring.mvc.view.suffix=.jsp

spring.datasource.url=jdbc:postgresql://localhost:5433/JSPWithPostgresql
spring.datasource.username=postgres
spring.datasource.password=自身のパスワード

# データベーススキーマ(テーブル)を生成する
spring.jpa.hibernate.ddl-auto=create
```

③ PostgreSQLにJSPWithPostgresqlのDatabaseを作成する

④ src/main/java/com.example.jspdemoに modelファイルとAnime.javaを作成する

```model/Anime.java
package model;

import javax.persistence.*;

@Entity
@Table(name = "ANIME")
public class Anime {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column
    private String name;

    @Column
    private int year;

    private Anime() {

    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }
}
```
⑤ src/main/javaにcom.example.jspdemoファイルと
MainApplication.javaを作成する

```MainApplication.java
package com.example.jspdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan("com.example.jspdemo")
public class MainApplication {

    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }
}
```
⑥ src/main/java/com.example.jspdemoにrepoファイルと
IAnimeRepsitory.javaを作成する

```repo / IAnimeRepsitory.java
package com.example.jspdemo.repo;

import com.example.jspdemo.model.Anime;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface IAnimeReponsitory extends JpaRepository<Anime, Long> {

}
```

⑦ src/main/java/com.example.jspdemoにserviceファイルと
AnimeService.javaを作成する

```service/AnimeService.java
package com.example.jspdemo.service;

import com.example.jspdemo.model.Anime;
import com.example.jspdemo.repo.IAnimeReponsitory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class AnimeService {

    @Autowired
    IAnimeReponsitory animeRepo;

    public List<Anime> getAllAnime() {
        List<Anime> animeList = new ArrayList<>();
        animeRepo.findAll().forEach(anime -> animeList.add(anime));

        return animeList;
    }

    public Anime getAnimeById(Long id) {
        return animeRepo.findById(id).get();
    }

    public boolean saveOrUpdateAnime(Anime anime) {
        Anime updatedAnime = animeRepo.save(anime);

        if animeRepo.findById(updatedAnime.getId() !=null) {
        return true;
        }
        return false;
}

    public boolean deleteAnime(Long id) {
        animeRepo.deleteById(id);

        if animeRepo.findById(id) !=null) {
        return true;
        }
        return false;
    }

}
```
## 3.コントローラーを作成する

① src/main/javaにcom.example.jspdemoにcontrollerファイルと
Animecontroller.javaを作成する

```controller/Animecontroller.java
package com.example.jspdemo.controller;

import com.example.jspdemo.model.AnimeService;
import com.example.jspdemo.service.AnimeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

@Controller
public class AnimeController {

    @Autowired
    AnimeService animeService;

    @GetMapping({"/","/viewAnimeList"})
    public String viewAnimeList(@ModelAttribute("message")String message, Model model) {
        model.addAttribute(attributeName:"animeList",animeService.getAllAnime());
        model.addAttribute(attributeName:"message",message);

        return "viewAnimeList";
    }

    @GetMapping("/addAnime")
    public String addAnime(@ModelAttribute("message")String message, Model model) {
        model.addAttribute(attributeName:"anime", new Anime());
        model.addAttribute(attributeName:"message",message);

        return "AddAnime";
    }

    @PostMapping("/saveAnime")
    public String saveAnime(Anime anime, RedirectAttributes redirectAttributes) {
        if (animeService, saveOrUpdateAnime(anime)){
           redirectAttributes.addFlashAttribute(attributeName "message", attributeVale:"Save Success");
           return "redirect:/viewAnimeList";
    }

        redirectAttributes.addFlashAttribute(attributeName "message", attributeVale:"Save Failure");
        return "redirect:/addAnime";
    }

    @GetMapping("/editAnime/{id}")
    public String editAnime(@PathVariable Long id, Model model){
      model.addAttribute (attributeNames: "anime" , animeService.getAnimeById(id));
      return "EditAnime";
    }
    
    @PostMapping("/editSaveAnime")
    public String editSaveAnime(Anime anime, RedirectAttributes redirectAttributes) {
        if (animeService, saveOrUpdateAnime(anime)){
           redirectAttributes.addFlashAttribute(attributeName "message", attributeVale:"edit Success");
           return "redirect:/viewAnimeList";
    }

        redirectAttributes.addFlashAttribute(attributeName "message", attributeVale:"edit Failure");
        return "redirect:/editAnime" + anime.getId();
    }

    @PostMapping("/deleteAnime/{id}")
    public String deleteAnime(@PathVariable Long id, RedirectAttributes redirectAttributes) {
        if (animeService, deleteAnime(id)){
           redirectAttributes.addFlashAttribute(attributeName "message", attributeVale:"Delete Success");
    }

        redirectAttributes.addFlashAttribute(attributeName "message", attributeVale:"Delete Failure");
        return "redirect:/addAnime";
    }
}
```

② src/mainにwebapp/WEB-INF/jspにViewAnimeList.jspファイルを作成する。

```ViewAnimeList.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%> <% taglib prefix="form"
uri="http://www.sprigframework.org/tags/form" %> <% taglib prefix="c"
uri="http://www.java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>
<head>
  <meta charset="ISO-8859-1" />
  <title>VIEW ANIME LIST</title>

  <link
    rel="stylesheet"
    href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
  />
  <script src="https://ajax.googleapis.com/ajax/libs/jquery.3.5.1/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>

  <style>
    a {
      color: white;
    }
    a:hover {
      color: white;
      text-decoration: none;
    }
  </style>
  <body>
    <div class="container">
      <h1 class="p-3">ANIME</h1>
      <form:form>
        <table>
          <tr>
            <th>Id</th>
            <th>Name</th>
            <th>Yeaar</th>
            <th>Edit</th>
            <th>Delete</th>
          </tr>
          <c:forEach var="anime" items="${animeList}">
            <tr>
              <td>${anime.id}</td>
              <td>${anime.name}</td>
              <td>${anime.year}</td>
              <td>
                <button type="button" class="btn btn-success">
                  <a href="/editAnime/${anime.id}">Edit</a>
                </button>
              </td>
              <td>
                <button type="button" class="btn btn-danger">
                  <a href="/deleteAnime/${anime.id}">Delete</a>
                </button>
              </td>
            </tr>
          </c:forEach>
        </table>
      </form:form>
      <button type="button" class="btn btn-primary btn-block">
        <a href="addAnime">Add New Anime</a>
      </button>
    </div>
  </body>
</head>
```
③ src/mainにwebapp/WEB-INF/jspにEditAnimeList.jspファイルを作成する。

```EditAnimeList.jsp


```

④ src/mainにwebapp/WEB-INF/jspにAddAnimeList.jspファイルを作成する。

```AddAnimeList.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%> <% taglib prefix="form"
uri="http://www.sprigframework.org/tags/form" %> <% taglib prefix="c"
uri="http://www.java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>
<head>
  <meta charset="ISO-8859-1" />
  <title>Add Anime</title>

  <link
    rel="stylesheet"
    href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
  />
  <link
    rel="stylesheet"
    href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css"
  />

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css"></script>

  <body>
    <div class="container">
      <h1 class="p-3">Add an Anime</h1>
      <form:form action="/saveAnime" method="post" modelAttribute="anime">
        <div class="row">
          <div class="form-group col-md-12">
            <label class="col-md-3" for="name">Name</label>
            <div class="form-group col-md-6">
              <form:input
                type="text"
                path="name"
                id="name"
                class="form-control input-sm"
                required="required"
              />
            </div>
          </div>
        </div>

        <div class="row">
          <div class="form-group col-md-12">
            <label class="col-md-3" for="name">Year</label>
            <div class="form-group col-md-6">
              <form:input
                type="text"
                path="name"
                id="name"
                class="form-control input-sm"
                required="required"
              />
            </div>
          </div>
        </div>

        <div class="row p-2">
          <div class="col-md-2">
            <button type="submit" value="Register" class="btn btn-success">
              Save
            </button>
          </div>
        </div>
      </form:form>
    </div>

    <script th:inline="javascript">
      window.onload = function(){
          var msg = [[${messeage}]];
          if(msg == "Save Success"){
            Command:toastr["success"]("User created successfully!!")
          } else if (msg == "Delete success"){
            Command:toastr["success"]("User deleted successfully!!")
          } else if (msg == "Delete Error"){
            Command:toastr["Error"]("Some error occurred, couldn't delete user")
        } else if (msg == "Edi Success"){
            Command:toastr["success"]("User updated successfully!!")
      }

      toastr.option = {
        "closeButton":true,
        "debug": false,
        "newestOnTop":false,
        "progressBar":true,
        "positionClass":"toast-top-right",

      }
    </script>
  </body>
</head>

```



## 参考サイト
[Connect a PostgreSQL database to a Spring Boot Application Tutorial](https://www.youtube.com/watch?v=ltvRsnka7Mo)
[Complete Project | CRUD Application from Scratch Tutorial | Spring Boot | PostgreSQL | JSP | JPA](https://www.youtube.com/watch?v=3_DdrUvfpYM)
[spring.jpa.hibernate.ddl-auto に設定可能な値](https://qiita.com/KenjiOtsuka/items/8450c407ba121fea8151)