<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>H2-Database on K-Life Hack | システムアーキテクチャ &amp; DevOps</title><link>https://klifehack.com/tags/h2-database/</link><description>Recent content in H2-Database on K-Life Hack | システムアーキテクチャ &amp; DevOps</description><generator>Hugo -- gohugo.io</generator><language>ja</language><lastBuildDate>Sat, 06 Jun 2026 09:50:48 +0900</lastBuildDate><atom:link href="https://klifehack.com/tags/h2-database/index.xml" rel="self" type="application/rss+xml"/><item><title>Spring Boot 3.xにおけるJakarta PersistenceとLombokを用いたデータ永続化レイヤーの構築</title><link>https://klifehack.com/p/spring-jpa-lombok-h2-setup/</link><pubDate>Sat, 06 Jun 2026 09:50:48 +0900</pubDate><guid>https://klifehack.com/p/spring-jpa-lombok-h2-setup/</guid><description>&lt;p&gt;現代のWebアプリケーションアーキテクチャにおいて、データのライフサイクル管理は極めて重要な要素です。MVCパターンやRESTful APIはHTTPリクエストを処理しレスポンスを返しますが、メモリ上のみで処理されるデータはアプリケーションの終了やシステム障害によって消失します。永続性を確保するためには、リレーショナルデータベース（RDBMS）などの永続化ストレージとの連携が不可欠です。&lt;/p&gt;
&lt;p&gt;しかし、Javaのオブジェクト指向パラダイム（クラス、カプセル化、関連性）と、リレーショナルデータベースのパラダイム（テーブル、行、列、外部キー制約）の間には、「オブジェクト関係のインピーダンスミスマッチ」と呼ばれる構造的な不一致が存在します。従来、このミスマッチを解消するためには、冗長でエラーの発生しやすいSQLクエリを手動で記述する必要がありました。&lt;/p&gt;
&lt;p&gt;この課題を解決するために標準化されたのが &lt;b&gt;Jakarta Persistence (旧 Java Persistence API: JPA)&lt;/b&gt; です。JPAはオブジェクト関係マッピング (ORM) フレームワークとして機能し、Javaオブジェクトをデータベースのテーブルに直接マッピングすることで、開発者がSQLを意識することなく直感的にデータを操作できる環境を提供します。&lt;/p&gt;
&lt;h2 id="2-h2データベースの特性と動作モード"&gt;2. H2データベースの特性と動作モード
&lt;/h2&gt;&lt;p&gt;開発、テスト、およびプロトタイピングの段階において、本番環境用データベース（PostgreSQLやOracleなど）をローカル環境に構築することは、インフラのオーバーヘッドを増加させます。この課題に対して、軽量なJavaベースのオープンソースリレーショナルデータベースである &lt;b&gt;H2 Database&lt;/b&gt; が広く利用されています。&lt;/p&gt;
&lt;p&gt;H2データベースは、アプリケーションのランタイム内に組み込まれる軽量なJARファイルとして動作するため、インストールの手間がかかりません。動作モードとしては、データベースがアプリケーションと同じJVM内で動作する「埋め込みモード (Embedded Mode)」と、独立したプロセスとして動作し複数の外部アプリケーションから同時に接続できる「サーバーモード (Server Mode)」の2つが提供されています。また、アプリケーションの実行ライフサイクルを超えてデータを保持する必要がない高速な統合テストに最適なインメモリ機能や、ブラウザ経由でデータベースを操作できるWebコンソール機能も備えています。デフォルトでは以下のURLからアクセス可能です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;http://localhost:8081/h2-console
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="3-データベースアクセスの進化jdbcからjpaへ"&gt;3. データベースアクセスの進化：JDBCからJPAへ
&lt;/h2&gt;&lt;p&gt;ORMフレームワークが普及する前、Javaアプリケーションは &lt;b&gt;Java Database Connectivity (JDBC)&lt;/b&gt; を使用してデータベースと通信していました。JDBCでは、低レベルのデータベースリソースの管理、SQL文字列の構築、および結果セットからJavaオブジェクトへのマッピングを手動で行う必要がありました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Connection conn &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PreparedStatement pstmt &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ResultSet rs &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;try&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; conn &lt;span style="color:#f92672"&gt;=&lt;/span&gt; DriverManager.&lt;span style="color:#a6e22e"&gt;getConnection&lt;/span&gt;(URL, USER, PASSWORD);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; String sql &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;SELECT id, name, email FROM students WHERE id = ?&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pstmt &lt;span style="color:#f92672"&gt;=&lt;/span&gt; conn.&lt;span style="color:#a6e22e"&gt;prepareStatement&lt;/span&gt;(sql);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pstmt.&lt;span style="color:#a6e22e"&gt;setLong&lt;/span&gt;(1, 1L);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; rs &lt;span style="color:#f92672"&gt;=&lt;/span&gt; pstmt.&lt;span style="color:#a6e22e"&gt;executeQuery&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (rs.&lt;span style="color:#a6e22e"&gt;next&lt;/span&gt;()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Student student &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Student();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; student.&lt;span style="color:#a6e22e"&gt;setId&lt;/span&gt;(rs.&lt;span style="color:#a6e22e"&gt;getLong&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; student.&lt;span style="color:#a6e22e"&gt;setName&lt;/span&gt;(rs.&lt;span style="color:#a6e22e"&gt;getString&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; student.&lt;span style="color:#a6e22e"&gt;setEmail&lt;/span&gt;(rs.&lt;span style="color:#a6e22e"&gt;getString&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;email&amp;#34;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} &lt;span style="color:#66d9ef"&gt;catch&lt;/span&gt; (SQLException e) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e.&lt;span style="color:#a6e22e"&gt;printStackTrace&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} &lt;span style="color:#66d9ef"&gt;finally&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (rs &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;try&lt;/span&gt; { rs.&lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;(); } &lt;span style="color:#66d9ef"&gt;catch&lt;/span&gt; (SQLException e) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (pstmt &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;try&lt;/span&gt; { pstmt.&lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;(); } &lt;span style="color:#66d9ef"&gt;catch&lt;/span&gt; (SQLException e) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (conn &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;try&lt;/span&gt; { conn.&lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;(); } &lt;span style="color:#66d9ef"&gt;catch&lt;/span&gt; (SQLException e) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;JDBCの主な課題として、接続の確立や例外処理、リソースの解放といった本質的ではないボイラープレートコードが大部分を占める点、SQLクエリが文字列としてハードコードされるためコンパイル時の型チェックが行われない点、そして &lt;code&gt;ResultSet&lt;/code&gt; から値を取り出してドメインオブジェクトに手動でマッピングする作業がタイポなどのエラーを誘発しやすい点が挙げられます。&lt;/p&gt;
&lt;p&gt;JPAは、これらの低レベルなJDBC操作を抽象化します。開発者は命令的なSQLを記述する代わりに、アノテーションを使用してドメインオブジェクトにマッピングを宣言します。JPAプロバイダ（主にHibernate）は、実行時に適切なSQLを自動的に生成して実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@PersistenceContext&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; EntityManager em;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; Student &lt;span style="color:#a6e22e"&gt;findStudent&lt;/span&gt;(Long id) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; em.&lt;span style="color:#a6e22e"&gt;find&lt;/span&gt;(Student.&lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;, id);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;saveStudent&lt;/span&gt;(Student student) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; em.&lt;span style="color:#a6e22e"&gt;persist&lt;/span&gt;(student);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;JPAを導入することで、一般的なCRUD操作が抽象化され、Javaのクラス構造がリレーショナルスキーマに自動的に変換されるため、インピーダンスミスマッチが解消されます。&lt;/p&gt;
&lt;h2 id="4-依存関係の定義と環境構築"&gt;4. 依存関係の定義と環境構築
&lt;/h2&gt;&lt;p&gt;Spring BootアプリケーションでJPAとH2データベースを使用するための、Gradleビルド定義ファイルの設定例です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-groovy" data-lang="groovy"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dependencies &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; implementation &lt;span style="color:#e6db74"&gt;&amp;#39;org.springframework.boot:spring-boot-starter-data-jpa&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; runtimeOnly &lt;span style="color:#e6db74"&gt;&amp;#39;com.h2database:h2&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; compileOnly &lt;span style="color:#e6db74"&gt;&amp;#39;org.projectlombok:lombok&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; annotationProcessor &lt;span style="color:#e6db74"&gt;&amp;#39;org.projectlombok:lombok&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; testImplementation &lt;span style="color:#e6db74"&gt;&amp;#39;org.springframework.boot:spring-boot-starter-test&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="5-jakarta-persistence-jpa-によるエンティティマッピング仕様"&gt;5. Jakarta Persistence (JPA) によるエンティティマッピング仕様
&lt;/h2&gt;&lt;p&gt;エンティティは、データベースのテーブルにマッピングされる軽量なドメインオブジェクトです。Spring Boot 3.x以降、永続化仕様は従来のJava EE名前空間（&lt;code&gt;javax.persistence.&lt;em&gt;&lt;/code&gt;）から、Jakarta EE名前空間（&lt;code&gt;jakarta.persistence.&lt;/em&gt;&lt;/code&gt;）に移行しています。&lt;/p&gt;
&lt;p&gt;主要なJPAマッピングアノテーションとして、対象クラスがJPAエンティティでありデータベーステーブルにマッピングされることを示す &lt;code&gt;@Entity&lt;/code&gt; があります。デフォルトではクラス名がテーブル名になりますが、&lt;code&gt;@Table&lt;/code&gt; アノテーションを使用することで明示的に指定可能です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Entity&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Table&lt;/span&gt;(name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;students&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Student&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;すべてのJPAエンティティは、レコードを一意に識別するための主キー（PK）を定義する必要があります。&lt;code&gt;@Id&lt;/code&gt; はフィールドを主キーとして指定し、&lt;code&gt;@GeneratedValue&lt;/code&gt; は主キーの生成戦略を設定します。&lt;code&gt;GenerationType.IDENTITY&lt;/code&gt; を指定すると、データベースの自動インクリメント機能に生成を委任します。&lt;/p&gt;
&lt;p&gt;また、&lt;code&gt;@Column&lt;/code&gt; アノテーションを使用することで、フィールドとデータベースカラムのマッピングをカスタマイズできます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Column&lt;/span&gt;(name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;email&amp;#34;&lt;/span&gt;, nullable &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;, length &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 50, unique &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; String email;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;nullable&lt;/code&gt; を &lt;code&gt;false&lt;/code&gt; に設定すると、生成されるDDLに &lt;code&gt;NOT NULL&lt;/code&gt; 制約が付与されます。&lt;code&gt;length&lt;/code&gt; は文字列カラムの最大長を定義し、&lt;code&gt;unique&lt;/code&gt; はカラムにユニーク制約を適用します。&lt;/p&gt;
&lt;h2 id="6-lombokの統合とエンティティ設計におけるアンチパターン"&gt;6. Lombokの統合とエンティティ設計におけるアンチパターン
&lt;/h2&gt;&lt;p&gt;Javaの標準的なカプセル化パターンでは、フィールドを &lt;code&gt;private&lt;/code&gt; に設定し、パブリックなGetter/Setterを提供します。また、JPAはリフレクションによるインスタンス化のためにデフォルトコンストラクタを要求します。これらを手動で記述するとコードが肥大化するため、Lombokを導入してコンパイル時に自動生成します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Entity&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Table&lt;/span&gt;(name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;students&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Getter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Setter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@NoArgsConstructor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Student&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;@Id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;@GeneratedValue&lt;/span&gt;(strategy &lt;span style="color:#f92672"&gt;=&lt;/span&gt; GenerationType.&lt;span style="color:#a6e22e"&gt;IDENTITY&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; Long id;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;@Column&lt;/span&gt;(nullable &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;, length &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 50)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; String name;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;@Column&lt;/span&gt;(nullable &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;, length &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 50, unique &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; String email;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;⚠️ &lt;b&gt;重要な警告：JPAエンティティにおける @Data の回避&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Lombokの &lt;code&gt;@Data&lt;/code&gt; アノテーションは、&lt;code&gt;@Getter&lt;/code&gt;、&lt;code&gt;@Setter&lt;/code&gt;、&lt;code&gt;@ToString&lt;/code&gt;、&lt;code&gt;@EqualsAndHashCode&lt;/code&gt;、&lt;code&gt;@RequiredArgsConstructor&lt;/code&gt; を一括で適用するため便利ですが、JPAエンティティへの適用は避けるべきです。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;@ToString&lt;/code&gt; や &lt;code&gt;@EqualsAndHashCode&lt;/code&gt; は、クラス内のすべてのフィールドを評価します。エンティティ間に双方向の関連（&lt;code&gt;@OneToMany&lt;/code&gt; と &lt;code&gt;@ManyToOne&lt;/code&gt; など）が存在する場合、&lt;code&gt;toString()&lt;/code&gt; や &lt;code&gt;hashCode()&lt;/code&gt; の呼び出しが相互参照を引き起こし、最終的に &lt;code&gt;StackOverflowError&lt;/code&gt; を発生させます。このため、エンティティクラスには &lt;code&gt;@Getter&lt;/code&gt;、&lt;code&gt;@Setter&lt;/code&gt;、&lt;code&gt;@NoArgsConstructor&lt;/code&gt; を個別に明示的に宣言することを推奨します。&lt;/p&gt;
&lt;h2 id="7-ddl自動生成ddl-autoとアプリケーション設定"&gt;7. DDL自動生成（ddl-auto）とアプリケーション設定
&lt;/h2&gt;&lt;p&gt;Spring Bootでは、&lt;code&gt;application.yaml&lt;/code&gt; を通じてデータベース接続、H2コンソール、およびHibernateのDDL生成動作を制御できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spring&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;datasource&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;url&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;driver-class-name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;org.h2.Driver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;username&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;sa&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;password&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;h2&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;console&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;enabled&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;path&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;/h2-console&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;jpa&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;hibernate&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ddl-auto&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;update&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;show-sql&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;hibernate&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;format_sql&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;spring.jpa.hibernate.ddl-auto&lt;/code&gt; の設定値と本番環境における安全性は以下の通りです。&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th style="text-align: left"&gt;オプション&lt;/th&gt;
					&lt;th style="text-align: left"&gt;説明&lt;/th&gt;
					&lt;th style="text-align: left"&gt;本番環境における安全性&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td style="text-align: left"&gt;&lt;code&gt;create&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: left"&gt;起動時に既存のテーブルを削除（Drop）し、新規テーブルを作成（Create）します。&lt;/td&gt;
					&lt;td style="text-align: left"&gt;&lt;b&gt;極めて危険&lt;/b&gt;（データ消失）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style="text-align: left"&gt;&lt;code&gt;create-drop&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: left"&gt;&lt;code&gt;create&lt;/code&gt; と同様ですが、アプリケーション終了時にすべてのテーブルを削除します。&lt;/td&gt;
					&lt;td style="text-align: left"&gt;&lt;b&gt;極めて危険&lt;/b&gt;（データ消失）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style="text-align: left"&gt;&lt;code&gt;update&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: left"&gt;エンティティの変更点を検出し、テーブル構造を変更（Alter）します。既存のデータやカラムは削除されません。&lt;/td&gt;
					&lt;td style="text-align: left"&gt;&lt;b&gt;危険&lt;/b&gt;（テーブルロックや不整合の要因）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style="text-align: left"&gt;&lt;code&gt;validate&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: left"&gt;エンティティ定義とデータベーススキーマを比較検証し、不一致がある場合は起動を停止します。&lt;/td&gt;
					&lt;td style="text-align: left"&gt;&lt;b&gt;安全&lt;/b&gt;（本番環境推奨）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style="text-align: left"&gt;&lt;code&gt;none&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: left"&gt;自動生成を行いません。&lt;/td&gt;
					&lt;td style="text-align: left"&gt;&lt;b&gt;安全&lt;/b&gt;（本番環境推奨）&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;ローカル開発環境では &lt;code&gt;create&lt;/code&gt; や &lt;code&gt;update&lt;/code&gt; が便利ですが、本番環境では予期せぬデータ消失を防ぐため、必ず &lt;code&gt;validate&lt;/code&gt; または &lt;code&gt;none&lt;/code&gt; を設定し、FlywayやLiquibaseなどの専用マイグレーションツールでスキーマを管理してください。&lt;/p&gt;
&lt;h2 id="8-api検証とcors回避"&gt;8. API検証とCORS回避
&lt;/h2&gt;&lt;p&gt;構築した永続化レイヤーおよびREST APIの動作確認には、PostmanなどのAPIクライアントを使用します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -X POST http://localhost:8081/api/students &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -H &lt;span style="color:#e6db74"&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -d &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;name&amp;#34;: &amp;#34;John Doe&amp;#34;, &amp;#34;email&amp;#34;: &amp;#34;john.doe@example.com&amp;#34;}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ブラウザ版のPostmanを使用する場合、同一生成元ポリシー（Same-Origin Policy）により、ローカルサーバー（&lt;code&gt;localhost&lt;/code&gt;）へのリクエストがCORS制限によってブロックされることがあります。この場合、ローカルマシンに &lt;b&gt;Postman Agent&lt;/b&gt; をインストールして実行することで、ブラウザの制限をバイパスし、ローカルのSpring Bootサーバーへ直接リクエストをルーティングできます。&lt;/p&gt;
&lt;p&gt;主要なHTTPリクエスト検証手順は以下の通りです。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;b&gt;データの登録 (POST)&lt;/b&gt;
URL: &lt;code&gt;http://localhost:8081/api/students&lt;/code&gt;
Headers: &lt;code&gt;Content-Type: application/json&lt;/code&gt;
Body (raw JSON):&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;John Doe&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;email&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;john.doe@example.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start="2"&gt;
&lt;li&gt;&lt;b&gt;データの取得 (GET)&lt;/b&gt;
URL: &lt;code&gt;http://localhost:8081/api/students&lt;/code&gt;
登録したデータがJSON配列として返却されることを確認します。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="9-configuration-notes"&gt;9. Configuration Notes
&lt;/h2&gt;&lt;p&gt;💡 堅牢なデータ永続化レイヤーを維持するために、以下のチェックリストを設計基準として適用してください。&lt;/p&gt;
&lt;p&gt;&lt;b&gt;エンティティの必須構成要素&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;クラスレベルに &lt;code&gt;@Entity&lt;/code&gt; が付与されていること。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@Id&lt;/code&gt; による主キー定義が存在すること。&lt;/li&gt;
&lt;li&gt;JPA仕様に準拠したデフォルトコンストラクタ（&lt;code&gt;@NoArgsConstructor&lt;/code&gt;）が定義されていること。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Lombokの適用基準&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@Data&lt;/code&gt; の使用を避け、&lt;code&gt;@Getter&lt;/code&gt;、&lt;code&gt;@Setter&lt;/code&gt; を個別に付与していること。&lt;/li&gt;
&lt;li&gt;双方向関連がある場合、循環参照による &lt;code&gt;StackOverflowError&lt;/code&gt; を防止する設計になっていること。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;データベーススキーマ管理&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;カラム制約（&lt;code&gt;nullable&lt;/code&gt;、&lt;code&gt;length&lt;/code&gt;）が &lt;code&gt;@Column&lt;/code&gt; で明示されていること。&lt;/li&gt;
&lt;li&gt;本番環境の &lt;code&gt;ddl-auto&lt;/code&gt; 設定が &lt;code&gt;validate&lt;/code&gt; または &lt;code&gt;none&lt;/code&gt; になっていること。&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>