この記事では、PostgreSQLデータベースの準備から始まり、Spring Bootを用いたCRUD操作のシンプルなブログ投稿アプリの作成までの一連の流れを学ぶことができます。データベースとテーブルの作成、環境変数の設定方法、Spring Bootプロジェクトの構成、各クラスの役割について詳しく解説します。
はじめに
Eclipseインストールがまだの方はこちら
PostgreSQLインストールがまだの方はこちら
PostgreSQLデータベースの準備
データベースとテーブル作成
コマンドプロンプトまたは、ターミナルを開きます。
- psqlに接続:
PostgreSQLにスーパーユーザー(通常はpostgres
)として接続します。
psql -U postgres
- データベースの作成:
blogdb
という名前のデータベースを作成します。
CREATE DATABASE blogdb;
- データベースに接続:
作成したデータベースに接続します。
\c blogdb
- テーブルの作成:
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
);
- テーブルが作成されたか確認:
テーブルが正しく作成されたか確認するために、次のコマンドを実行します。
テーブル一覧を表示:
\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:アプリケーションのエントリーポイント
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ページ)とデータを結びつけます。
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(投稿)」のエンティティ(モデル)クラスです。
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)を定義しています。
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:このインターフェースでは、ブログ投稿の操作に必要なメソッドを定義しています。
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
インターフェースを実装し、実際のデータ操作を行います。
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のデザインを整えています。
/* 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:
で始まる特殊なタグを使って、サーバーサイドのデータを埋め込み、ページを動的に生成します。
<!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はアプリケーションのエントリーポイント
です。
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ページ)とデータを結びつけます。
クラス定義とアノテーション
@Controller
@RequestMapping("/posts")
public class PostController {
- @Controller:このアノテーションはクラスがコントローラーであることをSpringに知らせます。コントローラーはリクエストを処理し、適切なビューにデータを渡します。
- @RequestMapping(“/posts”):このアノテーションは、
/posts
というURLに対して、このコントローラーが対応することを意味します。このクラス内のメソッドは、/posts
で始まるURLを処理します。
依存性注入
@Autowired
private PostService postService;
- @Autowired:Springが
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を返す
}
- @GetMapping:
@GetMapping
は、HTTP GETリクエストを処理するメソッドを指定します。ここでは/posts
へのGETリクエストに対応します。 - List posts = postService.findAll():
postService
を使って全ての投稿を取得し、posts
というリストに格納します。 - model.addAttribute:
model
にデータを追加して、ビュー(HTMLページ)で利用できるようにします。ここではposts
リストと新しい投稿用の空のPost
オブジェクトを追加しています。 - return “posts”:
posts.html
というビュー名を返します。ビューはresources/templates
フォルダにあるHTMLファイルとして指定されます。
投稿の保存メソッド
@PostMapping
public String save(@ModelAttribute Post post) {
postService.save(post); // 投稿を保存
return "redirect:/posts"; // 投稿一覧ページにリダイレクト
}
- @PostMapping:HTTP POSTリクエストを処理します。フォームからの投稿データを受け取り、新しい投稿の保存や既存投稿の更新に使います。
- @ModelAttribute Post post:
post
というオブジェクトがフォームのデータを自動的に受け取ります。 - postService.save(post):投稿データをデータベースに保存します。新規投稿も編集済みの投稿もこのメソッドで処理されます。
- return “redirect:/posts”:
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を返す(編集フォームも同じビューで表示)
}
- @GetMapping(“/{id}/edit”):URLの
{id}
部分が投稿IDを示し、これを使って編集対象の投稿を指定します。 - @PathVariable Long id:URLから取得した
id
をid
パラメーターとして使います。 - postService.findById(id):
id
をもとに特定の投稿を取得します。 - post.ifPresent:投稿が存在する場合、
model.addAttribute
でpost
オブジェクトをビューに渡します。 - return “posts”:編集用のフォームも
posts.html
で表示されます。
特定のIDの投稿を削除するメソッド
@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
というテーブルに対応し、ブログ投稿のデータを保持します。
クラスのアノテーション
@Entity
@Table(name = "posts")
public class Post {
- @Entity:このアノテーションは、クラスがJPAエンティティであることをSpringに伝えます。エンティティとはデータベーステーブルに対応するクラスのことです。このクラスの各フィールド(
id
、title
、content
など)がデータベースのカラムにマッピングされます。 - @Table(name = “posts”):このアノテーションで、データベース内の
posts
テーブルにマッピングすることを指定します。これにより、Post
クラスのデータはデータベース上のposts
テーブルに保存されます。
プライマリキーの設定
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
- @Id:このアノテーションは、
id
フィールドがテーブルのプライマリキーであることを示します。プライマリキーは、各レコードを一意に識別するための特別な列です。 - @GeneratedValue(strategy = GenerationType.IDENTITY):このアノテーションで、
id
の値が自動生成されるようにします。GenerationType.IDENTITY
はデータベースが自動でインクリメント(増加)するIDを生成する方法です。これにより、id
はデータベースに新しいレコードが追加されるごとに自動的に一意な値が割り当てられます。
フィールドの宣言
@Column(nullable = false)
private String title;
@Column(nullable = false)
private String content;
- @Column(nullable = false):このアノテーションで、
title
とcontent
は必須フィールドであり、データベースではNULL
を許可しないことを示しています。ブログ投稿にタイトルと内容は必須なので、このように設定します。 - private String titleとprivate String content:
title
とcontent
は、ブログ投稿のタイトルと本文を表すフィールドです。String
型で宣言されており、これらのデータがデータベースに保存されます。
ゲッターとセッター
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)を定義しています。リポジトリは、データベースとのやり取りを管理する役割を持ち、アプリケーションの他の部分から簡単にデータ操作ができるようにするためのインターフェースです。
インターフェースとアノテーション
@Repository
public interface PostRepository extends JpaRepository<Post, Long> {
- @Repository:このアノテーションは、インターフェースがリポジトリとしてSpringに認識されるようにします。リポジトリはデータベースとのやり取りを管理する役割があり、Springにより自動的にインスタンス化され、必要な場所で使えるようになります。
- public interface PostRepository:
PostRepository
はインターフェースであり、ブログの投稿に関連するデータベース操作を定義します。このインターフェースを作成することで、コード内でデータベース操作をシンプルに利用できます。 - extends JpaRepository:
JpaRepository
インターフェースを継承することで、データベース操作の標準的な機能(CRUD操作)が自動的に追加されます。
JpaRepositoryの役割
- JpaRepository:
JpaRepository
は、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リクエストを処理する部分)とリポジトリ(データベースアクセスを管理する部分)の間を仲介する役割を持ちます。このインターフェースでは、ブログ投稿の操作に必要なメソッドを定義しています。
インターフェースの定義
public interface PostService {
- public interface PostService:
PostService
はインターフェースであり、サービス層で実装されるべきメソッドを定義しています。このインターフェースを実装するクラスが、実際のビジネスロジックを提供します。 - サービス層の役割は、データベース操作を直接行わずにビジネスロジックを提供し、コントローラー層が必要とするデータを取得・処理することです。
findAll メソッド
List<Post> findAll();
- List findAll():このメソッドは、全ての投稿をリスト形式で取得するためのものです。
- List:メソッドが返す型で、複数の
Post
オブジェクトをリスト形式で返します。 - findAll():
Post
オブジェクトのすべてのレコードをデータベースから取得します。
findById メソッド
Optional<Post> findById(Long id);
- Optional findById(Long id):特定のIDを持つ投稿を取得します。取得した投稿が存在するかどうかわからない場合に使用します。
- Optional:Javaの
Optional
クラスは、取得した投稿が存在しない場合にnull
の代わりとして使われます。 - findById(Long id):
id
を引数に取り、そのIDに対応する投稿を検索します。
save メソッド
void save(Post post);
- void save(Post post):投稿をデータベースに保存します。このメソッドは、新規投稿の保存と、既存投稿の更新の両方で使用されます。
- void:メソッドが値を返さないことを示しています。
- save(Post post):
Post
オブジェクトを受け取り、そのデータをデータベースに保存します。新しい投稿も編集済みの投稿も、このメソッドで処理できます。
deleteById メソッド
void deleteById(Long id);
- void deleteById(Long id):指定されたIDの投稿をデータベースから削除します。
- deleteById(Long id):
id
を引数に取り、そのIDの投稿を削除します。
このPostService
インターフェースを使用することで、コントローラーや他のクラスからデータベース操作を隠蔽し、ビジネスロジックに集中できるようになります。各メソッドは、投稿に関する標準的な操作(取得、保存、削除)を提供し、実装クラスが実際のロジックを提供します。
PostServiceImpl.Javaの解説
このコードは、ブログ投稿のデータを操作するサービス層の実装クラスです。このクラスはPostService
インターフェースを実装し、実際のデータ操作を行います。PostRepository
(リポジトリ)を使ってデータベースにアクセスし、ビジネスロジックを提供しています。
クラス宣言とアノテーション
@Service
public class PostServiceImpl implements PostService {
- @Service:このアノテーションは、クラスがサービス層であることをSpringに示します。この層は、ビジネスロジック(データ処理のルールや操作)を実行します。
- public class PostServiceImpl implements PostService:
PostServiceImpl
クラスは、PostService
インターフェースを実装しています。この実装クラスが、実際のデータ操作のロジックを提供する役割を持ちます。
PostRepositoryの依存性注入
@Autowired
private PostRepository postRepository;
- @Autowired:Springが
postRepository
フィールドに自動的にPostRepository
インスタンスを注入します。これにより、リポジトリのメソッドを使ってデータベースにアクセスできます。 - private PostRepository postRepository:このフィールドは、データベースとやりとりするためのリポジトリを保持します。
PostServiceImpl
内で使用し、投稿データの取得・保存・削除などを行います。
findAll メソッド
@Override
public List<Post> findAll() {
return postRepository.findAll();
}
- public List findAll():全ての投稿を取得し、リストとして返すメソッドです。
- return postRepository.findAll():
postRepository.findAll()
を呼び出して、データベース内のすべてのPost
をリスト形式で取得します。
findById メソッド
@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 メソッド
@Override
public void save(Post post) {
postRepository.save(post);
}
- public void save(Post post):新しい投稿を保存するか、既存の投稿を更新するメソッドです。
- postRepository.save(post):
postRepository.save(post)
を呼び出して、post
オブジェクトをデータベースに保存または更新します。
deleteById メソッド
@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」の解説をします。
コメント