|
Spring Boot+JPAを使用した開発手順
JPAを使用してSpring Boot Webアプリケーションからデータベースに接続するサンプルです。
もう一度おさらいをすると、Spring BootでDBアクセス処理の実現方法は大きく
(1) JdbcTemplate (2) MyBatis (3) JPAの方法があります。
(1) JdbcTemplateの方法は
- build.gradle(またはpom.xml)にJDBCへの依存性を定義
- application.propertiesにデータベース接続情報を定義
- JdbcTemplateを使用したサービスクラスまたはControllerクラスを作成
- 画面のThymeleaf HTMLを作成
となり、(2) MyBatisの方法は
- build.gradle(またはpom.xml)にMyBatisへの依存性を定義
- application.propertiesにデータベース接続情報を定義
- Entityクラスを作成
- Mapperインターフェースを作成。必要に応じてmapper XMLファイルも作成
- Mapperを使用したサービスクラスまたはControllerクラスを作成
- 画面のThymeleaf HTMLを作成
となります。(3) JPAの方法もよく似ていて
- build.gradle(またはpom.xml)にJPAへの依存性を定義
- application.propertiesにデータベース接続情報を定義
- Entityクラスを作成
- Repositoryインターフェースを作成
- Repositoryを使用したサービスクラスまたはControllerクラスを作成
- 画面のThymeleaf HTMLを作成
の手順となります。
SQLをほぼ常に直書きするMyBatisに対して、JPAではシンプルな単一表のCRUDアクセスに限れば、
Javaコードをより短く記述できます。
[1] build.gradle(またはpom.xml)に依存性を記述
build.gradleの例です。
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
[2] データベース接続情報をapplication.propertiesに記述
次にsrc/main/resources/application.resourcesに接続情報を追記します。
spring.datasource.url=jdbc:h2:C:/usr/dbms/h2/nkdb/nkdb;IFEXISTS=TRUE
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=nkuser
spring.datasource.password=********
spring.jpa.show-sql=true
|
最後の行はJPAのデフォルトのORマッパーであるHibernateが自動生成するSQLをコンソールに出力するオプションです。
開発環境ではtrueにしておき、デバッグが済んだ本番環境ではfalseにする運用が有効そうです。
[3] エンティティクラスを作る
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import lombok.Data;
@Data
@Entity
public class Items {
@Id
@GeneratedValue
private Integer itemId;
@Column
private String itemName;
@Column
private String sizeDesc;
@Column
private Integer price;
@Column
private String makerDesc;
// ↓表示には不要でも、findByCategoryIdというメソッドを作るなら列定義が必要
@Column
private Integer categoryId;
}
|
JPAでも、MyBatisによく似たエンティティクラスを作ります。
JPA由来のアノテーションは @Entiry、@Id、@GeneratedValue、@Columnです。
簡単に言えばそれだけなのですが、幾つか注意点があります。
まず、JPAでデータベースアクセスを行うだけならLombok由来の@Dataアノテーションは不要です。
ただし、このEntityを(Form Beanに詰め替える等をせずに)
そのままThymeleafのth:each等でループしながら表示に使う場合、
各変数にpublicなgetter/setterが必要なので、@Dataか@Getter+@Setterを付ける必要があります。
またテーブルの名前を明示的に定義せずJPAに任せる場合、
自分のようなド素人が引っかかるのは単数形/複数形の扱いです。
「品目マスタ」のテーブル名は単数形のITEMとはせずに複数形のITEMSとすることが多いと思います。
JPAでは、テーブル名がItemsだったらEntityクラス名はItem、というような変換はしてくれないので、
「Entityなのに複数形…?」と一瞬迷ってしまうかもしれません。
[4] Repositoryインターフェースを作る
MyBatisのMapperの代わりにJPAではRepositoryという物を作りますが、
両方ともJavaのインターフェースである点は共通です。
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import local.jpaentity.Items;
@Repository
public interface ItemsRepository extends JpaRepository<Items, Long> {
List<Items> findByCategoryId(Integer categoryId);
}
|
JpaRepositoryインターフェースを継承することと、
@Repositoryアノテーションを付けることはそれぞれ役割が違うのでごく簡単に整理します。
JpaRepositoryを継承すると、
save(),findById(),findAll()など基礎的なCRUD操作用のメソッドがが自動的に定義されます。
また、上の「findByCategoryId」のように、メソッド名を一定のルールに合わせることで、
SELECT文のSQLを全く記述しなくても、合ったSQLが自動的に生成されます。
一方、@Repositoryアノテーションはデータベース操作だけなら必須ではありませんが、
SpringがDAOクラスと認識してDB接続を管理してくれるのと、
処理中の例外がDataAccessExceptionになるので一元処理が可能な利点があるため、
原則両方を組で付けるといいと思います。
[5] サービスクラスやControllerクラスを作る
ここでは横着をして、サービスクラスを作らずに直接ControllerからRepositoryを参照しています。
MyBatisのMapperの代わりにJPAのRepositoryをfinal変数で定義し、
@RequiredArgsConstructorでinjectする書き方はMyBatisと全く同じです。
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import local.jpaentity.Items;
import local.jparepo.ItemsRepository;
import lombok.RequiredArgsConstructor;
@Controller
@RequiredArgsConstructor
public class JpaTestController {
private final ItemsRepository repo;
@RequestMapping("/jpatest")
public String doQuery(Model model) throws Exception {
List<Items> rlist = repo.findByCategoryId(Integer.valueOf(3));
model.addAttribute("query", "ITEM_SEARCH");
model.addAttribute("rowCount", Integer.valueOf(rlist.size()));
model.addAttribute("recordList", rlist);
return "jpatest";
}
}
|
[6] ThymeLeafでHTMLを作る
SELECT結果を表示するだけのThymeLeaf HTMLの例です。default.cssは省略します。
このThymeLeafはMyBatisとJPAで全く違いはありません。
必要に応じてDBアクセスというバックエンド処理だけを後から差し替える運用も可能そうです。
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head><title>DB検索のテスト</title><meta charset="UTF-8" /></head>
<body>
<link href="/css/default.css" th:href="@{/css/default.css}" rel="stylesheet"></link>
<h3>DB検索のテスト(JPA)</h3>
[[${query}]]<br>
<div th:if="${rowCount} gt 0" th:text="|${rowCount}件のデータが見つかりました。|"></div>
<div th:if="${rowCount} eq 0" th:text="データが見つかりませんでした。"></div>
<h3>検索結果</h3>
<table class="default">
<tr><th>品目コード</th><th>品目名称</th><th>単位</th><th>単価</th><th>販売者</th></tr>
<tr th:each="row : ${recordList}">
<td th:text="${row.itemId}" style="text-align:right;"></td>
<td th:text="${row.itemName}" class="tdtest"></td>
<td th:text="${row.sizeDesc}" class="tdtest"></td>
<td th:text="${row.price}" style="text-align:right;"></td>
<td th:text="${row.makerDesc}" class="tdtest"></td>
</tr>
</table>
<form th:action="@{/}"><input type="submit" value="メインメニューに戻る"/></form>
</body></html>
|

(first uploaded 2026/01/28 last updated 2026/01/28, URANO398)
|