Spring Boot 3を使った簡単なTODOアプリの作成

# はじめに
この記事では、Spring Boot 3を使って簡単なTODOアプリを作成する方法を紹介します。TODOアプリは、基本的なCRUD（Create, Read, Update, Delete）操作を通じてSpring Bootの基本を学ぶのに最適です。

# 前提条件
* Spring Boot 3.0
* Java 17以上
* MavenまたはGradle

# プロジェクトのセットアップ
1. Spring Initializrを使用してプロジェクトを生成します。以下の依存関係を追加します。

    * Spring Web
    * Spring Data JPA
    * H2 Database
    * Spring Boot DevTools
 <br>   
2. プロジェクトの生成が完了したら、IDEにインポートします。

# ディレクトリ構造
```
src/main/java/com/example/todoapp
|-- TodoAppApplication.java
|-- controller
|   |-- TodoController.java
|-- model
|   |-- Todo.java
|-- repository
|   |-- TodoRepository.java
|-- service
    |-- TodoService.java

```

# 1. エントリーポイントの作成
TodoAppApplication.java
```java
package com.example.todoapp;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TodoAppApplication {

    public static void main(String[] args) {
        SpringApplication.run(TodoAppApplication.class, args);
    }
}

```

# 2. モデルの作成
Todo.java
※Lombokを使ってGetter/Setterの記述を省略しても構いません。

```java
package com.example.todoapp.model;

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

@Entity
public class Todo {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;
    private boolean completed;

    // Getters and Setters

    public Long getId() {
        return id;
    }

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

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public boolean isCompleted() {
        return completed;
    }

    public void setCompleted(boolean completed) {
        this.completed = completed;
    }
}

```

# 3. リポジトリの作成
TodoRepository.java
```java
package com.example.todoapp.repository;

import com.example.todoapp.model.Todo;
import org.springframework.data.jpa.repository.JpaRepository;

public interface TodoRepository extends JpaRepository<Todo, Long> {
}

```

# 4. サービスの作成
TodoService.java
※Lombokを使ったDIのやり方でも問題ありません。
```java
package com.example.todoapp.service;

import com.example.todoapp.model.Todo;
import com.example.todoapp.repository.TodoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class TodoService {

    @Autowired
    private TodoRepository todoRepository;

    public List<Todo> getAllTodos() {
        return todoRepository.findAll();
    }

    public Optional<Todo> getTodoById(Long id) {
        return todoRepository.findById(id);
    }

    public Todo createTodo(Todo todo) {
        return todoRepository.save(todo);
    }

    public Todo updateTodo(Long id, Todo todoDetails) {
        Todo todo = todoRepository.findById(id).orElseThrow(() -> new RuntimeException("Todo not found"));
        todo.setTitle(todoDetails.getTitle());
        todo.setCompleted(todoDetails.isCompleted());
        return todoRepository.save(todo);
    }

    public void deleteTodo(Long id) {
        todoRepository.deleteById(id);
    }
}

```

# 5. コントローラの作成
TodoController.java
```java
package com.example.todoapp.controller;

import com.example.todoapp.model.Todo;
import com.example.todoapp.service.TodoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/todos")
public class TodoController {

    @Autowired
    private TodoService todoService;

    @GetMapping
    public List<Todo> getAllTodos() {
        return todoService.getAllTodos();
    }

    @GetMapping("/{id}")
    public ResponseEntity<Todo> getTodoById(@PathVariable Long id) {
        Todo todo = todoService.getTodoById(id).orElseThrow(() -> new RuntimeException("Todo not found"));
        return ResponseEntity.ok(todo);
    }

    @PostMapping
    public Todo createTodo(@RequestBody Todo todo) {
        return todoService.createTodo(todo);
    }

    @PutMapping("/{id}")
    public ResponseEntity<Todo> updateTodo(@PathVariable Long id, @RequestBody Todo todoDetails) {
        Todo updatedTodo = todoService.updateTodo(id, todoDetails);
        return ResponseEntity.ok(updatedTodo);
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteTodo(@PathVariable Long id) {
        todoService.deleteTodo(id);
        return ResponseEntity.noContent().build();
    }
}

```

# 6. アプリケーションの設定
application.properties
```properties
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

```

# 7. アプリケーションの起動とテスト
1. アプリケーションを起動します。
2. ブラウザで http://localhost:8080/h2-console にアクセスし、H2コンソールに接続します。
3. TODO APIをPostmanやcurlなどのツールを使ってテストします。

例:

* TODOリストを取得する: GET /api/todos
* 特定のTODOを取得する: GET /api/todos/{id}
* 新しいTODOを作成する: POST /api/todos
* TODOを更新する: PUT /api/todos/{id}
* TODOを削除する: DELETE /api/todos/{id}

# さいごに
この記事では、Spring Boot 3を使用して簡単なTODOアプリを作成する方法を紹介しました。この基本的なCRUDアプリケーションを通じて、Spring Bootの基本的な使い方や、JPAを使用したデータベース操作の方法を学ぶことができます。