SpringBoot + Postgresqlでアプリを作成してみた【CRUD API】

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

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

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

- Project: Maven
- Language: Java
- SpringBoot: 3.0.9

- Group: com.example
- Artifact: CRUD Rest API
- Name : CRUD Rest API
- Description: Demo projects for Spring Boot with React
- Package name: com.wazooinc.springboot_with_react

Dependencies
- Spring Boot Web
- Spring Data JPA SQL
- PostgreSQL Driver SQL

## 2.dockerとdatabaseを接続する

① docker-compose.ymlを作成する

```docker-compose.yml
version: '3.9'

services:
  java_db:
    container_name: java_db
    image: postgres:12
    ports:
      - 5432:5432
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: postgres
    volumes:
      - pgdata:/var/lib/postgresql/data

  volumes: pgdata:{}
```
② docker composeを行う

```
docker compose up -d java_db
docker compose ps -a

```
③ application.propertiesでDB内で自動的に更新されるように定義する

```application.properties
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
```
## 3.アプリを作成する

①crudフォルダにuserフォルダとUserファイルを作成する

```crud/user/User.java
package com.example.crud.user;

import jakarta.persistence.*;

@Entity
@Table(name = "users")
public class User {

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

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

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

    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 String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}
```
② userフォルダにUserRepositoryファイルを作成する

```UserRepository.java
package com.example.crud.user;

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

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

}
```
③ userフォルダにUserControllerファイルを作成する

```UserController.java
package com.example.crud.user;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
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.RequestBody;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;

@RestController
@RequestMapping("/api/users")
public class UserController {

    @Autowired
    private UserRepository userRepository;

    @GetMapping
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }

    @GetMapping("/{id}")
    public User getUserById(@PathVariable Long id) {
        return userRepository.findById(id).get();
    }

    @PostMapping
    public User createUser(@RequestBody User user) {
        return userRepository.save(user);
    }

    @PutMapping("/{id}")
    public User updateUser(@PathVariable Long id, @RequestBody User user) {
        User existingUser = userRepository.findById(id).get();
        existingUser.setName(user.getName());
        existingUser.setEmail(user.getEmail());
        return userRepository.save(existingUser);
    }

    @DeleteMapping("/{id}")
    public String deleteUser(@PathVariable Long id) {
        try {
            userRepository.deleteById(id);
            return "User deleted successfully";
        } catch (Exception e) {
            return "User not found";
        }
    }
}
```
④Javaプロジェクトをクリーンしてパッケージングする

```
mvn clean package
```

## 4.dockerを作成する

① Dockerfileを作成する

```
touch Dockerfile
```
```
//Dockerfile

FROM openjdk:17-jdk-alpine

COPY live-0.0.1-SNAPSHOT.jar app-1.0.0.jar

ENTRYPOINT [ "java", "-jar", "app-1.0.0.jar" ]
```
② docker-compose.ymlを編集する

```docker-compose.yml
version: '3.9'

services:
  java_app:
    container_name: java_name
    image: francescoxx/java_app:1.0.0
    build: .
    ports:
      - 8080:8000
    environment:
      - DATABASE_URL=jdbc:postgresql://java_db:5432/postgres
      - DATABASE_USERNANE=postgresql
      - DATABASE_PASSWORD=postgresql
    depends_on:
      - java_db

  java_db:
    container_name: java_db
    image: postgres:12
    ports:
      - 5432:5432
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: postgres
    volumes:
      - pgdata:/var/lib/postgresql/data

  volumes: pgdata:{}
```


③ application.propertiesを編集する

```application.properties
spring.datasource.url=${DATABASE_URL}
spring.datasource.username=${DATABASE_USERNAME}
spring.datasource.password=${DATABASE_PASSWORD}
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
```

④ Mavenを使用してJavaプロジェクトをクリーンしてパッケージ化する

```
mvn clean package -DekioTests
```
⑤　docker のコマンドを行う

```
docker images
docker compose build

```



## 参考サイト
[Spring Boot Tutorial using JDBC + Connection Pool + Flyway + JDBC Template + SQL and Docker 😲](https://www.youtube.com/watch?v=CJjHdchLY9Y)