JavaSpringフレームワーク

【Java】Spring BootでCRUD操作アプリ作成(1/2)

Spring Boot CRUD操作1解説ページのアイキャッチ画像 Java

この記事では、PostgreSQLデータベースの準備から始まり、Spring Bootを用いたCRUD操作のシンプルなブログ投稿アプリの作成までの一連の流れを学ぶことができます。データベースとテーブルの作成、環境変数の設定方法、Spring Bootプロジェクトの構成、各クラスの役割について詳しく解説します。

はじめに

Eclipseインストールがまだの方はこちら

PostgreSQLインストールがまだの方はこちら

PostgreSQLデータベースの準備

データベースとテーブル作成

コマンドプロンプトまたは、ターミナルを開きます。

  1. psqlに接続:
    PostgreSQLにスーパーユーザー(通常はpostgres)として接続します。
psql -U postgres
  1. データベースの作成:
    blogdbという名前のデータベースを作成します。
CREATE DATABASE blogdb;
  1. データベースに接続:
    作成したデータベースに接続します。
\c blogdb
  1. テーブルの作成:
    postsテーブルを以下のSQL文で作成します。
CREATE TABLE posts (
   id SERIAL PRIMARY KEY,
   title VARCHAR(255) NOT NULL,
   content TEXT NOT NULL,
   created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
  1. テーブルが作成されたか確認:
    テーブルが正しく作成されたか確認するために、次のコマンドを実行します。

テーブル一覧を表示:

\dt

テーブルの列を表示:

\d posts

環境変数の設定

環境変数を設定することで、パスワードなどをSpring Bootで変数として扱えます。
セキュリティのためにコードベースに直接書き込むことなく、環境設定で管理できます。

Windowsの場合

“your_username”は、今回スーパーユーザーの「“postgres”」を設定します。
“your_password”は、PostgreSQLインストール時に設定したパスワードを設定します。

setx POSTGRESQL_DB_USERNAME "your_username"
setx POSTGRESQL_DB_PASSWORD "your_password"

Linux/Macの場合

export POSTGRESQL_DB_USERNAME="your_username"
export POSTGRESQL_DB_PASSWORD="your_password"

以下のシステム環境の編集画面で確認できます。

Spring Bootブログアプリ作成

Spring Bootプロジェクト作成

Eclipseを起動して「ファイル」→「新規」→「Spring スターター・プロジェクト」を選択します。

  • 名前:「blog
  • タイプ:「Maven
  • Javaバージョン:「21
  • パッケージ:「com.example.blog
  • 次へ」をクリックします。

依存関係の設定

  • Spring Boot バージョン:「3.3.5
  • デフォルトで設定されている項目と「Spring Data JPA」「Thymeleaf」「PostgreSQL Deiver」を選択します。
    ※PostgreSQL Driver は左のSQL欄にあります。
  • 完了」をクリックします。
  • Spring Boot Dev Tools

開発者の生産性を向上させるツールセットです。アプリケーションの自動再起動、ライブリロード、リモートデバッグなどの機能を提供し、開発プロセスを効率化します。

  • Lombok

Javaのボイラープレートコードを削減するためのライブラリです。アノテーションを使用してgetter、setter、constructorなどを自動生成し、コードの簡潔さを向上させます。

  • Spring Data JPA

データベースアクセスを簡素化するフレームワークです。JPAを使用してオブジェクトとリレーショナルデータベースのマッピングを行い、リポジトリインターフェースの実装を自動生成します。

  • PostgreSQL Driver

PostgreSQLデータベースとJavaアプリケーションを接続するためのJDBCドライバーです。Spring BootアプリケーションがPostgreSQLと通信するために必要です。

  • Thymeleaf

Javaベースのテンプレートエンジンで、HTMLテンプレートにデータを埋め込んでWebページを生成します。Spring Bootと統合しやすく、サーバーサイドでの動的なコンテンツ生成に使用されます。

  • Spring Web

Webアプリケーション開発のための包括的なフレームワークです。RESTful APIの作成、MVCアーキテクチャの実装、HTTPリクエスト処理などの機能を提供します。

フォルダ階層

blog/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/
│   │   │       └── example/
│   │   │           └── blog/
│   │   │               ├── BlogApplication.java          // メインアプリケーションクラス
│   │   │               ├── controller/
│   │   │               │   └── PostController.java       // コントローラー
│   │   │               ├── model/
│   │   │               │   └── Post.java                 // エンティティ
│   │   │               ├── repository/
│   │   │               │   └── PostRepository.java       // リポジトリインターフェース
│   │   │               └── service/
│   │   │                   ├── PostService.java          // サービスインターフェース
│   │   │                   └── /impl
│   │   │                        └── PostServiceImpl.java  // サービスの実装クラス       
│   │   │                     
│   │   └── resources/
│   │       ├── static/                                   // 静的リソース(CSS, JSなど)
│   │       │   └── css/
│   │       │       └── styles.css
│   │       ├── templates/                                // Thymeleafテンプレート
│   │       │   └── posts.html                            // 投稿用のHTMLテンプレート
│   │       └── application.properties                    // アプリケーション設定
│   └── test/
│       └── java/
│           └── com/
│               └── example/
│                   └── blog/
│                       ├── PostControllerTests.java      // コントローラーのテストクラス
│                       └── PostServiceImplTests.java     // サービスのテストクラス
└── pom.xml                                               // Mavenの設定ファイル

コード例

BlogApplication.java:アプリケーションのエントリーポイント

Java
package com.example.blog;

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

@SpringBootApplication // Spring Bootアプリケーションのエントリーポイントとして機能
public class BlogApplication {

    // アプリケーションのメインメソッド
    public static void main(String[] args) {
        // Spring Bootアプリケーションの実行を開始
        SpringApplication.run(BlogApplication.class, args);
    }
}

PostController.java:投稿の一覧表示、新規投稿の保存、編集、削除の各機能を提供し、ビュー(Webページ)とデータを結びつけます。

Java
package com.example.blog.controller;

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

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.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.example.blog.model.Post;
import com.example.blog.service.PostService;

@Controller
@RequestMapping("/posts")
public class PostController {

    @Autowired
    private PostService postService; // PostServiceのインスタンスを注入

    // 投稿一覧を表示するメソッド
    @GetMapping
    public String list(Model model) {
        List<Post> posts = postService.findAll(); // 全ての投稿を取得
        model.addAttribute("posts", posts); // 投稿リストをモデルに追加
        model.addAttribute("post", new Post()); // 新規投稿用の空のPostオブジェクトを追加
        return "posts"; // posts.htmlを返す
    }

    // 新規投稿または編集済み投稿を保存するメソッド
    @PostMapping
    public String save(@ModelAttribute Post post) {
        postService.save(post); // 投稿を保存
        return "redirect:/posts"; // 投稿一覧ページにリダイレクト
    }

    // 特定のIDの投稿を編集するメソッド
    @GetMapping("/{id}/edit")
    public String edit(@PathVariable Long id, Model model) {
        Optional<Post> post = postService.findById(id); // IDで投稿を検索
        post.ifPresent(value -> model.addAttribute("post", value)); // 投稿が存在する場合、モデルに追加
        return "posts"; // posts.htmlを返す(編集フォームも同じビューで表示)
    }

    // 特定のIDの投稿を削除するメソッド
    @PostMapping("/{id}/delete")
    public String delete(@PathVariable Long id) {
        postService.deleteById(id); // IDで投稿を削除
        return "redirect:/posts"; // 投稿一覧ページにリダイレクト
    }
}

Post.java:Spring BootアプリケーションでJPA(Java Persistence API)を使ってデータベースに保存される「Post(投稿)」のエンティティ(モデル)クラスです。

Java
package com.example.blog.model;

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

@Entity // JPAのエンティティとして、このクラスがデータベーステーブルに対応することを示す
@Table(name = "posts") // このエンティティがマッピングされるデータベースのテーブル名を指定
public class Post {

    @Id // プライマリキーとして使用するフィールドを指定
    @GeneratedValue(strategy = GenerationType.IDENTITY) // プライマリキーの生成戦略を「IDENTITY」に設定
    private Long id;

    @Column(nullable = false) // タイトルは必須フィールドとして、NULLを許可しない設定
    private String title;

    @Column(nullable = false) // コンテンツも必須フィールドとして、NULLを許可しない設定
    private String content;

    // ゲッターとセッター

    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 String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

PostRepository.java:Spring Data JPAを使ってブログ投稿をデータベースから取得したり保存したりするためのリポジトリ(Repository)を定義しています。

Java
package com.example.blog.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.example.blog.model.Post;

@Repository // このインターフェースがリポジトリであることを示す
public interface PostRepository extends JpaRepository<Post, Long> {
    // JpaRepository<Post, Long>を継承することで、Postエンティティに対する標準的なCRUD操作を利用可能
}

PostService.java:このインターフェースでは、ブログ投稿の操作に必要なメソッドを定義しています。

Java
package com.example.blog.service;

import java.util.List;
import java.util.Optional;
import com.example.blog.model.Post;

public interface PostService {
    
    /**
     * データベース内のすべての投稿を取得します。
     * @return 投稿のリスト
     */
    List<Post> findAll();

    /**
     * 指定されたIDに基づいて、投稿を取得します。
     * @param id 投稿のID
     * @return 該当する投稿のOptionalオブジェクト(存在しない場合は空)
     */
    Optional<Post> findById(Long id);

    /**
     * 新しい投稿を保存するか、既存の投稿を更新します。
     * @param post 保存する投稿オブジェクト
     */
    void save(Post post);

    /**
     * 指定されたIDに基づいて投稿を削除します。
     * @param id 削除する投稿のID
     */
    void deleteById(Long id);
}

PostServiceImpl.java:このクラスはPostServiceインターフェースを実装し、実際のデータ操作を行います。

Java
package com.example.blog.service.impl;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.blog.model.Post;
import com.example.blog.repository.PostRepository;
import com.example.blog.service.PostService;

@Service // サービス層を示すアノテーション。ビジネスロジックを担う。
public class PostServiceImpl implements PostService {

    @Autowired // PostRepositoryインスタンスの依存性注入
    private PostRepository postRepository;

    @Override
    public List<Post> findAll() {
        // すべての投稿を取得し、リストとして返す
        return postRepository.findAll();
    }

    @Override
    public Optional<Post> findById(Long id) {
        // 指定されたIDの投稿を取得し、Optionalでラップして返す
        return postRepository.findById(id);
    }

    @Override
    public void save(Post post) {
        // 新規投稿を保存または既存投稿を更新する
        postRepository.save(post);
    }

    @Override
    public void deleteById(Long id) {
        // 指定されたIDの投稿をデータベースから削除する
        postRepository.deleteById(id);
    }
}

styles.css:HTMLのデザインを整えています。

CSS
/* src/main/resources/static/css/styles.css */

:root {
    --primary-bg-color: #f9f9f9; /* 背景色 */
    --form-bg-color: #ffffff; /* フォームの背景色 */
    --button-bg-color: #28a745; /* 通常ボタンの背景色 */
    --button-hover-bg-color: #218838; /* ホバー時のボタン色 */
    --delete-button-bg-color: #dc3545; /* 削除ボタンの色 */
    --button-text-color: #ffffff; /* ボタンのテキスト色 */
}

body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 20px;
    background-color: var(--primary-bg-color);
}

h1, h2 {
    text-align: center;
}

section {
    max-width: 600px; /* 最大幅を設定 */
    margin: 0 auto;   /* 中央揃え */
    padding: 20px;
    background: var(--form-bg-color); /* 背景色をフォームに設定 */
    border-radius: 5px; /* 角を丸くする */
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); /* 影をつける */
}

form {
    padding: 20px;
}

label {
    display: block; /* ラベルをブロック要素にする */
    margin-bottom: 5px; /* 下のマージン */
}

input[type="text"],
textarea {
    width: 100%; /* 幅を100%に */
    padding: 10px; /* 内側の余白 */
    margin-bottom: 20px; /* 下のマージン */
    border: 1px solid #ccc; /* 枠線 */
    border-radius: 4px; /* 角を丸くする */
}

button {
    padding: 10px 15px; /* 内側の余白 */
    background-color: var(--button-bg-color); /* ボタンの背景色 */
    color: var(--button-text-color); /* テキストの色 */
    border: none; /* 枠線を消す */
    border-radius: 5px; /* 角を丸くする */
    cursor: pointer; /* カーソルをポインターに */
}

button:hover {
    background-color: var(--button-hover-bg-color); /* ホバー時の色 */
}

ul {
    list-style-type: none; /* リストのスタイルを消す */
    padding: 0; /* パディングを消す */
    max-width: 600px; /* 最大幅を設定 */
    margin: 0 auto; /* 中央揃え */
}

li {
    margin-bottom: 20px; /* 下のマージン */
    padding: 10px; /* 内側の余白 */
    background: var(--form-bg-color); /* 背景色を白に */
    border-radius: 5px; /* 角を丸くする */
    box-shadow: 0 1px 5px rgba(0, 0, 0, 0.1); /* 影をつける */
}

h3 {
    text-align: center; /* タイトルを中央揃え */
}

.delete-button {
    background-color: var(--delete-button-bg-color); /* 削除ボタンの色 */
}

.delete-button:hover {
    background-color: #c82333; /* ホバー時の色 */
}

.edit-link {
    display: inline-block; /* インラインブロックにしてボタン風に */
    padding: 10px 15px; /* 内側の余白 */
    background-color: var(--button-bg-color); /* 通常ボタンの色 */
    color: var(--button-text-color); /* テキストの色 */
    border: none; /* 枠線を消す */
    border-radius: 5px; /* 角を丸くする */
    cursor: pointer; /* カーソルをポインターに */
    text-decoration: none; /* 下線を消す */
}

.edit-link:hover {
    background-color: var(--button-hover-bg-color); /* ホバー時の色 */
}

posts.html:HTML内にth:で始まる特殊なタグを使って、サーバーサイドのデータを埋め込み、ページを動的に生成します。

HTML
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>ブログ投稿</title>
    <link rel="stylesheet" type="text/css" href="/css/styles.css">
    <script>
        // 投稿削除確認のポップアップ表示
        function confirmDelete() {
            return confirm("本当にこの投稿を削除しますか?");
        }
    </script>
</head>
<body>
    <h1>ブログ投稿</h1>
    
    <div class="container">
        <!-- 投稿の新規作成または編集用セクション -->
        <section>
            <form th:action="@{/posts}" th:object="${post}" method="post">
                <!-- 投稿IDを隠しフィールドとして保持(新規作成時はnull) -->
                <input type="hidden" th:field="*{id}" />
                
                <!-- 新規投稿時と編集時で見出しを切り替え -->
                <h2 th:if="${post.id == null}">新規投稿</h2>
                <h2 th:if="${post.id != null}">投稿の編集</h2>

                <!-- タイトル入力欄 -->
                <label>タイトル:</label>
                <input type="text" th:field="*{title}" required /> <!-- 必須項目 -->

                <!-- 内容入力欄 -->
                <label>内容:</label>
                <textarea th:field="*{content}" required></textarea> <!-- 必須項目 -->

                <!-- 新規保存ボタンまたは更新ボタンを表示 -->
                <button type="submit" th:text="${post.id == null} ? '投稿を保存' : '投稿を更新'"></button>
                
                <!-- 編集時のみ表示される投稿一覧に戻るリンク -->
                <a th:if="${post.id != null}" th:href="@{/posts}" style="margin-left: 10px;">投稿一覧に戻る</a>
            </form>
        </section>

        <!-- 投稿一覧セクション(新規投稿時のみ表示) -->
        <h2 th:if="${post.id == null}">投稿一覧</h2>
        <ul>
            <!-- 投稿リストの表示。投稿ごとにタイトル、内容、編集・削除リンクを含む -->
            <li th:each="post : ${posts}">
                <h3 th:text="${post.title}">投稿タイトル</h3>
                <p th:text="${post.content}">投稿内容</p>
                
                <!-- 編集リンク。選択した投稿の編集画面に遷移 -->
                <a th:href="@{/posts/{id}/edit(id=${post.id})}" class="edit-link">編集</a>
                
                <!-- 削除フォーム。確認ポップアップを表示してから削除 -->
                <form th:action="@{/posts/{id}/delete(id=${post.id})}" method="post" style="display:inline;" onsubmit="return confirmDelete();">
                    <button type="submit" class="delete-button">削除</button>
                </form>
            </li>
        </ul>
    </div>
</body>
</html>

application.properties:データベース接続情報やサーバーポート、ログ設定など、アプリケーションの構成情報を管理します

spring.application.name=blog
spring.datasource.url=jdbc:postgresql://localhost:5432/blogdb
spring.datasource.username=${POSTGRESQL_DB_USERNAME}
spring.datasource.password=${POSTGRESQL_DB_PASSWORD}
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.thymeleaf.cache=false

pom.xml

pom.xmlはMavenによるプロジェクト管理において不可欠なファイルであり、依存関係、ビルド設定、プラグインなどを一元管理することで、開発者が効率的にプロジェクトをビルド、テスト、デプロイできるようにします。

実行結果を確認

データベースの確認方法:

投稿、編集、削除の操作時のデータベースの状態も確認してみてください。コマンドもしくはpgAdimn4(GUIツール)で状態を確認できます。

PostgreSQLにログイン:

psql -U postgres

「blogdb」に接続:

\c blogdb

投稿データ一覧を表示:SELECT * FROM テーブル名;

SELECT * FROM posts;

実行方法:

プロジェクトを選択した状態で、実行ボタンをクリックもしくは「∇ボタン」→「実行」「Spring Bootアプリケーション」をクリックします。

ブラウザで「http://localhost:8080/posts」にアクセスします。

実行画面:

タイトルと内容入力して「投稿を保存」をクリックします。

投稿一覧に投稿内容が表示されます。
投稿一覧では「編集」「削除」を選択できます。

編集を選択すると、投稿の更新ができます。

コードの解説

BlogApplication.javaの解説

BlogApplication.javaはアプリケーションのエントリーポイントです。

Java
package com.example.blog;

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

@SpringBootApplication // Spring Bootアプリケーションのエントリーポイントとして機能
public class BlogApplication {

    // アプリケーションのメインメソッド
    public static void main(String[] args) {
        // Spring Bootアプリケーションの実行を開始
        SpringApplication.run(BlogApplication.class, args);
    }
}
  • @SpringBootApplication: このアノテーションは、@Configuration, @EnableAutoConfiguration, @ComponentScanをまとめたもので、Spring Bootアプリケーションとしての起動設定を行います。
  • mainメソッド: アプリケーションのエントリーポイントとして、SpringApplication.runメソッドを呼び出し、Spring Bootアプリケーションの実行を開始します。

PostController.javaの解説

コントローラーの役割は、アプリケーションが受け取ったリクエストを処理し、ビュー(Webページ)とデータを結びつけます。


クラス定義とアノテーション

Java
@Controller
@RequestMapping("/posts")
public class PostController {
  • @Controller:このアノテーションはクラスがコントローラーであることをSpringに知らせます。コントローラーはリクエストを処理し、適切なビューにデータを渡します。
  • @RequestMapping(“/posts”):このアノテーションは、/postsというURLに対して、このコントローラーが対応することを意味します。このクラス内のメソッドは、/postsで始まるURLを処理します。

依存性注入

Java
@Autowired
private PostService postService;
  • @Autowired:SpringがpostServiceという依存関係を自動的に注入します。依存性注入により、コードは他のクラスと疎結合になり、メンテナンスしやすくなります。
  • PostServicepostServiceは、ブログ投稿に関するビジネスロジックを提供するサービスです。このクラスはコントローラーが投稿データを取得・保存・削除する際に利用します。

投稿一覧を表示するメソッド

Java
@GetMapping
public String list(Model model) {
    List<Post> posts = postService.findAll(); // 全ての投稿を取得
    model.addAttribute("posts", posts); // 投稿リストをモデルに追加
    model.addAttribute("post", new Post()); // 新規投稿用の空のPostオブジェクトを追加
    return "posts"; // posts.htmlを返す
}
  • @GetMapping@GetMappingは、HTTP GETリクエストを処理するメソッドを指定します。ここでは/postsへのGETリクエストに対応します。
  • List posts = postService.findAll()postServiceを使って全ての投稿を取得し、postsというリストに格納します。
  • model.addAttributemodelにデータを追加して、ビュー(HTMLページ)で利用できるようにします。ここではpostsリストと新しい投稿用の空のPostオブジェクトを追加しています。
  • return “posts”posts.htmlというビュー名を返します。ビューはresources/templatesフォルダにあるHTMLファイルとして指定されます。

投稿の保存メソッド

Java
@PostMapping
public String save(@ModelAttribute Post post) {
    postService.save(post); // 投稿を保存
    return "redirect:/posts"; // 投稿一覧ページにリダイレクト
}
  • @PostMapping:HTTP POSTリクエストを処理します。フォームからの投稿データを受け取り、新しい投稿の保存や既存投稿の更新に使います。
  • @ModelAttribute Post postpostというオブジェクトがフォームのデータを自動的に受け取ります。
  • postService.save(post):投稿データをデータベースに保存します。新規投稿も編集済みの投稿もこのメソッドで処理されます。
  • return “redirect:/posts”redirect:/postsにより、投稿の一覧ページにリダイレクトします。

特定のIDの投稿を編集するメソッド

Java
@GetMapping("/{id}/edit")
public String edit(@PathVariable Long id, Model model) {
    Optional<Post> post = postService.findById(id); // IDで投稿を検索
    post.ifPresent(value -> model.addAttribute("post", value)); // 投稿が存在する場合、モデルに追加
    return "posts"; // posts.htmlを返す(編集フォームも同じビューで表示)
}
  • @GetMapping(“/{id}/edit”):URLの{id}部分が投稿IDを示し、これを使って編集対象の投稿を指定します。
  • @PathVariable Long id:URLから取得したididパラメーターとして使います。
  • postService.findById(id)idをもとに特定の投稿を取得します。
  • post.ifPresent:投稿が存在する場合、model.addAttributepostオブジェクトをビューに渡します。
  • return “posts”:編集用のフォームもposts.htmlで表示されます。

特定のIDの投稿を削除するメソッド

Java
@PostMapping("/{id}/delete")
public String delete(@PathVariable Long id) {
    postService.deleteById(id); // IDで投稿を削除
    return "redirect:/posts"; // 投稿一覧ページにリダイレクト
}
  • @PostMapping(“/{id}/delete”):投稿の削除にはPOSTリクエストを使い、URLの{id}で削除対象の投稿IDを指定します。
  • postService.deleteById(id):投稿を削除するためのpostServiceメソッドです。
  • return “redirect:/posts”:投稿を削除した後、再び投稿の一覧ページにリダイレクトします。

このコードにより、ブログ投稿アプリケーションの基本的なCRUD(作成・読み込み・更新・削除)機能を実現できます。それぞれのメソッドは特定のHTTPリクエストに対応し、適切なデータのやり取りを行います。

Post.javaの解説

このコードは、Spring BootアプリケーションでJPA(Java Persistence API)を使ってデータベースに保存される「Post(投稿)」のエンティティ(モデル)クラスです。このクラスのオブジェクトは、postsというテーブルに対応し、ブログ投稿のデータを保持します。


クラスのアノテーション

Java
@Entity
@Table(name = "posts")
public class Post {
  • @Entity:このアノテーションは、クラスがJPAエンティティであることをSpringに伝えます。エンティティとはデータベーステーブルに対応するクラスのことです。このクラスの各フィールド(idtitlecontentなど)がデータベースのカラムにマッピングされます。
  • @Table(name = “posts”):このアノテーションで、データベース内のpostsテーブルにマッピングすることを指定します。これにより、Postクラスのデータはデータベース上のpostsテーブルに保存されます。

プライマリキーの設定

Java
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
  • @Id:このアノテーションは、idフィールドがテーブルのプライマリキーであることを示します。プライマリキーは、各レコードを一意に識別するための特別な列です。
  • @GeneratedValue(strategy = GenerationType.IDENTITY):このアノテーションで、idの値が自動生成されるようにします。GenerationType.IDENTITYはデータベースが自動でインクリメント(増加)するIDを生成する方法です。これにより、idはデータベースに新しいレコードが追加されるごとに自動的に一意な値が割り当てられます。

フィールドの宣言

Java
@Column(nullable = false)
private String title;

@Column(nullable = false)
private String content;
  • @Column(nullable = false):このアノテーションで、titlecontentは必須フィールドであり、データベースではNULLを許可しないことを示しています。ブログ投稿にタイトルと内容は必須なので、このように設定します。
  • private String titleprivate String contenttitlecontentは、ブログ投稿のタイトルと本文を表すフィールドです。String型で宣言されており、これらのデータがデータベースに保存されます。

ゲッターとセッター

Java
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 String getContent() {
    return content;
}

public void setContent(String content) {
    this.content = content;
}
  • ゲッター(Getter):各フィールドの現在の値を取得するためのメソッドです。たとえば、getId()idの値を返し、getTitle()titleの値を返します。
  • セッター(Setter):フィールドの値を設定するためのメソッドです。たとえば、setId(Long id)idに新しい値を設定し、setTitle(String title)titleの値を設定します。

ゲッターとセッターは、データの取得と変更を簡単に行えるようにするための標準的な方法です。


このコード全体によって、Postエンティティはデータベース上のpostsテーブルと対応し、ブログの投稿データを保存・取得できるようになります。各アノテーションとフィールドがそれぞれデータベースとの関連付けを担い、データをしっかりと管理します。

PostRepository.Javaの解説

このコードは、Spring Data JPAを使ってブログ投稿をデータベースから取得したり保存したりするためのリポジトリ(Repository)を定義しています。リポジトリは、データベースとのやり取りを管理する役割を持ち、アプリケーションの他の部分から簡単にデータ操作ができるようにするためのインターフェースです。


インターフェースとアノテーション

Java
@Repository
public interface PostRepository extends JpaRepository<Post, Long> {
  • @Repository:このアノテーションは、インターフェースがリポジトリとしてSpringに認識されるようにします。リポジトリはデータベースとのやり取りを管理する役割があり、Springにより自動的にインスタンス化され、必要な場所で使えるようになります。
  • public interface PostRepositoryPostRepositoryはインターフェースであり、ブログの投稿に関連するデータベース操作を定義します。このインターフェースを作成することで、コード内でデータベース操作をシンプルに利用できます。
  • extends JpaRepositoryJpaRepositoryインターフェースを継承することで、データベース操作の標準的な機能(CRUD操作)が自動的に追加されます。

JpaRepositoryの役割

  • JpaRepositoryJpaRepositoryは、Spring Data JPAが提供する便利なインターフェースで、データベースに対する多くの標準的な操作(Create、Read、Update、Delete)をサポートしています。
  • Post:データベース操作の対象となるエンティティクラス(Postエンティティ)を指定します。
  • Long:エンティティの主キー(ID)の型です。PostクラスのidフィールドはLong型で定義されているため、ここでもLong型を指定しています。

標準的なCRUD操作

このインターフェースにはメソッドを追加せずに、すでに用意されているJpaRepositoryの標準メソッドが利用できます。

  • save():新しい投稿を保存したり、既存の投稿を更新したりします。
  • findById():特定のIDを持つ投稿を取得します。
  • findAll():すべての投稿を取得します。
  • deleteById():特定のIDの投稿を削除します。

このPostRepositoryインターフェースを使用することで、標準的なデータ操作がシンプルに実装でき、ビジネスロジックに集中できます。データベースにアクセスするための複雑なSQLを書かなくても、Spring Data JPAが標準的な操作をサポートしてくれるため、コーディングが効率的になります。

PostService.Javaの解説

このコードは、ブログ投稿に対するサービス層のインターフェースを定義しています。サービス層は、ビジネスロジックを含み、コントローラー(Webリクエストを処理する部分)とリポジトリ(データベースアクセスを管理する部分)の間を仲介する役割を持ちます。このインターフェースでは、ブログ投稿の操作に必要なメソッドを定義しています。


インターフェースの定義

Java
public interface PostService {
  • public interface PostServicePostServiceはインターフェースであり、サービス層で実装されるべきメソッドを定義しています。このインターフェースを実装するクラスが、実際のビジネスロジックを提供します。
  • サービス層の役割は、データベース操作を直接行わずにビジネスロジックを提供し、コントローラー層が必要とするデータを取得・処理することです。

findAll メソッド

Java
List<Post> findAll();
  • List findAll():このメソッドは、全ての投稿をリスト形式で取得するためのものです。
  • List:メソッドが返す型で、複数のPostオブジェクトをリスト形式で返します。
  • findAll()Postオブジェクトのすべてのレコードをデータベースから取得します。

findById メソッド

Java
Optional<Post> findById(Long id);
  • Optional findById(Long id):特定のIDを持つ投稿を取得します。取得した投稿が存在するかどうかわからない場合に使用します。
  • Optional:JavaのOptionalクラスは、取得した投稿が存在しない場合にnullの代わりとして使われます。
  • findById(Long id)idを引数に取り、そのIDに対応する投稿を検索します。

save メソッド

Java
void save(Post post);
  • void save(Post post):投稿をデータベースに保存します。このメソッドは、新規投稿の保存と、既存投稿の更新の両方で使用されます。
  • void:メソッドが値を返さないことを示しています。
  • save(Post post)Postオブジェクトを受け取り、そのデータをデータベースに保存します。新しい投稿も編集済みの投稿も、このメソッドで処理できます。

deleteById メソッド

Java
void deleteById(Long id);
  • void deleteById(Long id):指定されたIDの投稿をデータベースから削除します。
  • deleteById(Long id)idを引数に取り、そのIDの投稿を削除します。

このPostServiceインターフェースを使用することで、コントローラーや他のクラスからデータベース操作を隠蔽し、ビジネスロジックに集中できるようになります。各メソッドは、投稿に関する標準的な操作(取得、保存、削除)を提供し、実装クラスが実際のロジックを提供します。

PostServiceImpl.Javaの解説

このコードは、ブログ投稿のデータを操作するサービス層の実装クラスです。このクラスはPostServiceインターフェースを実装し、実際のデータ操作を行います。PostRepository(リポジトリ)を使ってデータベースにアクセスし、ビジネスロジックを提供しています。


クラス宣言とアノテーション

Java
@Service
public class PostServiceImpl implements PostService {
  • @Service:このアノテーションは、クラスがサービス層であることをSpringに示します。この層は、ビジネスロジック(データ処理のルールや操作)を実行します。
  • public class PostServiceImpl implements PostServicePostServiceImplクラスは、PostServiceインターフェースを実装しています。この実装クラスが、実際のデータ操作のロジックを提供する役割を持ちます。

PostRepositoryの依存性注入

Java
@Autowired
private PostRepository postRepository;
  • @Autowired:SpringがpostRepositoryフィールドに自動的にPostRepositoryインスタンスを注入します。これにより、リポジトリのメソッドを使ってデータベースにアクセスできます。
  • private PostRepository postRepository:このフィールドは、データベースとやりとりするためのリポジトリを保持します。PostServiceImpl内で使用し、投稿データの取得・保存・削除などを行います。

findAll メソッド

Java
@Override
public List<Post> findAll() {
    return postRepository.findAll();
}
  • public List findAll():全ての投稿を取得し、リストとして返すメソッドです。
  • return postRepository.findAll()postRepository.findAll()を呼び出して、データベース内のすべてのPostをリスト形式で取得します。

findById メソッド

Java
@Override
public Optional<Post> findById(Long id) {
    return postRepository.findById(id);
}
  • public Optional findById(Long id):特定のIDに基づいて投稿を取得するメソッドです。
  • return postRepository.findById(id)postRepository.findById(id)を呼び出して、そのIDに対応するPostを取得します。Optionalでラップすることで、投稿が見つからなかった場合のnullの扱いを容易にします。

save メソッド

Java
@Override
public void save(Post post) {
    postRepository.save(post);
}
  • public void save(Post post):新しい投稿を保存するか、既存の投稿を更新するメソッドです。
  • postRepository.save(post)postRepository.save(post)を呼び出して、postオブジェクトをデータベースに保存または更新します。

deleteById メソッド

Java
@Override
public void deleteById(Long id) {
    postRepository.deleteById(id);
}
  • public void deleteById(Long id):指定されたIDの投稿を削除するメソッドです。
  • postRepository.deleteById(id)postRepository.deleteById(id)を呼び出して、指定されたIDの投稿をデータベースから削除します。

このPostServiceImplクラスは、PostServiceインターフェースのメソッドを実装して、投稿に関するビジネスロジックを提供します。PostRepositoryを使うことで、データベース操作を直接行わずに、簡単に投稿データの取得・保存・削除を行えるようになります。この実装により、サービス層でのデータ操作が統一され、コントローラー層や他のコンポーネントから再利用しやすくなります。

まとめ

  • PostgreSQLデータベースのセットアップとテーブル作成の方法
  • 環境変数を使用してデータベース接続情報を管理する手順
  • Spring Bootアプリケーションのプロジェクト構成と、フォルダ階層の設計
  • アプリケーションのCRUD機能の実装とその動作確認方法
  • 主要クラス(BlogApplication.java, PostController.java, Post.java, PostRepository.java, PostService.java, PostServiceImpl.java)の詳細なコード解説

この記事を通じて、PostgreSQLとSpring Bootを組み合わせたCRUDアプリの構築方法が学べます。また、環境変数を用いたセキュアな設定方法や、MVCパターンに基づくコード構成についても理解が深まります。

次のページでは「posts.html」「application.properties」の解説をします。

未経験でもWEBスキルを取得したい方
  • Javaコース
    Javaプログラミングを基礎から応用まで、体系的に学べる実践的なカリキュラムが特徴です。「マインクラフト」を通じてJavaの基本文法とフレームワークの概念を学びます。また、実際のプロジェクト開発を通じて、データベース連携やWebアプリケーション開発のスキルを身につけることができます。

コメント

タイトルとURLをコピーしました