Spring Data REST で RESTful Webサービスを作ってみよう

Spring Data REST で RESTful Webサービスを作ってみよう

商品の全件取得、ID指定による取得、追加、更新、部分更新、削除の機能をもつRESTful WebサービスをSpring Data RESTを使って作成する方法を紹介します。

なお、今回作成したアプリケーションに以下のような機能を拡張する方法も今後紹介する予定です。

  • Spring Data RESTで、Bean Validationによる入力検証を行う
  • Spring Data RESTで、条件検索に対応した一覧取得を行う
    • 商品名の部分一致検索とか、価格がいくら以下のものを検索など
  • Spring Data RESTで、関連したエンティティのデータも一括して取得する
  • 画像のアップロードに対応したRESTful Web APIを作成する

Spring Data REST とは

Spring Data RESTは、「簡単なコードを用意するだけで、自動的にRESTfulなAPIを構築できる」ライブラリです。これを利用することで迅速にRESTful Webサービスを構築できます。

サンプルコード

完成版のサンプルコードは、 以下のGitLabリポジトリからダウンロードしてください。
ダウンロード

手順: [コード]ボタン クリック⇒ソースコードをダウンロード⇒zip等を選択

動作確認に必要なもの

ひな型プロジェクトの作成

サンプルコードを使う場合、既にプロジェクトは作成済みなので、この作業は不要です。プロジェクトの作成から始めたい場合の解説です。

プロジェクトを作成する際、Spring Initializer のDependenciesに、以下を追加します。

  • Spring Web : WebアプリやREST Web サービスを作る際に必要
  • Spring Data JPA : JPAを使ってEntityをDBに永続化するためのライブラリ
  • Rest Repositories : Spring Data RESTのライブラリ
  • MySQL Driver : サンプルアプリでは、DBとしてMySQLを使うので

Spring Initializer その他の項目の設定

ProjectMaven
LanguageJava
Spring Boot4.0.0以上
Groupcom.example
Artifact, Nameitems
Package namecom.example.items
PackagingJar
ConfigurationProperties
Java25

データベースの作成

アプリケーションからアクセスするデータベースおよびユーザーを作成しておきます。 create-schema-spring.sqlはサンプルコードの直下にあります。こちらのSQLを実行してください。

DROP DATABASE IF EXISTS itemsdb;
CREATE DATABASE itemsdb CHARACTER SET utf8mb4;
DROP USER IF EXISTS 'user-itemsdb';
CREATE USER 'user-itemsdb' IDENTIFIED BY 'P@ssw0rd';
GRANT ALL PRIVILEGES ON itemsdb.* to 'user-itemsdb';
USE itemsdb;
SHOW DATABASES;

設定ファイルの準備

application.propertiesファイルに以下の設定をします。(サンプルコードでは、設定済み)

spring.application.name=items

# DataSource
spring.datasource.url=jdbc:mysql://localhost:3306/itemsdb
spring.datasource.username=user-itemsdb
spring.datasource.password=P@ssw0rd
spring.jpa.database=mysql
spring.sql.init.encoding=utf-8

# for Spring Data REST : root path
spring.data.rest.basePath=/api

# for Jakarta Persistence
# spring.jpa.hibernate.ddl-auto
#   none   : 何もしない
#   update : アプリ起動時に、Entityに対応するテーブルがなければ作成。あればそのまま。
#   create : アプリ起動時に、Entityに対応するテーブルがなければ作成。あればデータを削除。
spring.jpa.hibernate.ddl-auto=update

作成が必要なソース

  • Entityクラス
    • アプリケーションで扱う永続化するデータ:REST APIのリソースとなるもの
    • データはEntityクラスごとに対応するテーブルに永続化される
    • テーブル名はEntityクラス名をスネークケースにしたものになる
      • 例 : EntityItemクラスの場合、テーブル名はitemになる
    • アプリケーション起動時にEntityクラスに対応するテーブルがない場合、JPA(Jakarta Persistence)により自動生成される
  • Repositoryインタフェース
    • EntityをDBに永続化するためのインタフェース

行う必要がないこと

  • テーブル物理設計、およびcreate table文の作成
    • JPA(Jakarta Persistence)により、テーブルはEntityクラスから自動生成できる
  • コントローラークラス、サービスクラスの作成
    • Spring Data REST が自動でエンドポイントを公開するため、作成は不要
  • 永続化層 実装クラスの作成
    • Spring Dataにより、起動時にDBに永続化する実装クラスは自動生成される

Entityクラスの作成

package com.example.items.entity;

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

import java.util.Objects;

/// 商品を表すエンティティクラス
@Entity
public class Item {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;     // 商品id (主キー、自動採番:AUTO_INCREMENT)
    private String name;    // 商品名
    private Integer price;  // 価格
    // setter/getter/toString/equals/hashCodeメソッド 省略
}
  • @Entity
    • Spring Data JPAのEntityクラスに付加する
  • @Id
    • テーブルの主キーに対応するフィールドに付加する
  • @GeneratedValue(strategy = GenerationType.IDENTITY)
    • id(主キー)を自動採番したい場合に付加する
    • Entityクラスからテーブルが自動生成される際、主キー列にAUTO_INCREMENTが付く

Repositoryインターフェースの作成

package com.example.items.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import com.example.items.entity.Item;

/// Itemエンティティを永続化するためのリポジトリーインタフェース
public interface ItemRepository extends JpaRepository<Item, Integer> {
}

JpaRepository<T, ID>インタフェースを継承して、リポジトリインタフェースを宣言します。

  • T : 永続化したいエンティティクラス(Item
  • ID : エンティティクラス 主キーの型 (Integer)

実行して、動作確認してみよう!

作成するソースはこれで完了です!
アプリケーション(com.example.items.ItemsApplication)を起動します。

起動後、DBにアクセスすると、itemテーブルができていることが分かります。

mysql> use itemsdb;
mysql> desc item;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | int          | NO   | PRI | NULL    | auto_increment |
| name  | varchar(255) | YES  |     | NULL    |                |
| price | int          | YES  |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+
3 rows in set (0.02 sec) 

ブラウザからRESTful Webサービスにアクセスします。
URL : http://localhost:8080/api

application.propertiesにspring.data.rest.basePath=/apiと設定しているため、REST APIのルートのパスは、”/api”になります。

{
  "_links" : {
    "items" : {
      "href" : "http://localhost:8080/api/items{?page,size,sort*}",
      "templated" : true
    },
    "profile" : {
      "href" : "http://localhost:8080/api/profile"
    }
  }
}

Spring Data REST では、HATEOAS(Hypermedia as the Engine of Application State)に基づいたレスポンスが返されます。これを見れば、次にどのような操作が可能かが分かります。 ここでは、items というリソースに対応したエンドポイント(/api/items)が存在していることが分かります。

補足:リソース名について

Entity クラスのリポジトリが存在する場合、デフォルトではクラス名を複数形にしたリソース名(例:Item → /items)でアクセスできるようになります。

なお、JpaRepository の標準機能により、リクエストパラメータに page, size, sort を指定するだけで、ページネーション(例:1ページあたり10件、0ページ目を取得)やソート(例:価格の降順など)か可能です。
※ page, size, sort を指定する操作は、のちほど説明します。

商品(items)の全件検索をしてみましょう。
URL : http://localhost:8080/api/items

{
  "_embedded" : {
    "items" : [ ]
  },
  "_links" : { ...省略... },
  "page" : { ...省略... }
}

_embeddedの中身が全件取得の結果です。まだ商品(Item)を登録していないので中身は空です。

新規登録(POST)

リソースの追加は、POSTでリクエストします。
URL : http://localhost:8080/api/items

リクエストボディに、登録したい情報を JSON 形式で指定します。サンプルコードの /WebAPI呼び出し フォルダにある items-post1.json 〜 items-post3.json のデータを使って、3件追加してみましょう。
{
  "name": "商品1",
  "price": 1980
}
更新系(POST/PUT/PATCH/DELETE)はブラウザではリクエストできないので、Postmanを使います。
Postmanでの設定

Postmanでの設定

設定したら、[Send]ボタンでリクエストを発行します。items-post1.json ~ items-post3.json の3件を追加してみましょう。

全件取得

商品の全件検索を行うと、3件のデータが追加できていることが確認できます。
URL : http://localhost:8080/api/items

{
  "_embedded" : {
    "items" : [ {
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/api/items/1"
        },
        "item" : {
          "href" : "http://localhost:8080/api/items/1"
        }
      },
      "name" : "商品1",
      "price" : 1980
    }, {
      "_links" : { ...省略... },
      "name" : "商品2",
      "price" : 890
    }, {
      "_links" : { ...省略... },
      "name" : "商品3",
      "price" : 2500
    } ]
  },
  "_links" : { ...省略... },
  "page" : {
    "number" : 0,
    "size" : 20,
    "totalElements" : 3,
    "totalPages" : 1
  }
}

ページネーションを指定しない場合、デフォルトで20件ごとにページングされます。

リクエストパラメータで、ページネーションやソートを指定することもできます。

http://localhost:8080/api/items?sort=priceソート
Entityのプロパティを指定
価格(price)でソート
http://localhost:8080/api/items?sort=price,desc,desc : 降順ソート
,asc : 昇順ソート
無指定 : DBのORDER BYデフォルト
http://localhost:8080/api/items?page=0&size=2ページネーション指定
1ページあたり2件(size=2)、
0ページ目(page=0)
http://localhost:8080/api/items?page=0&size=2&sort=priceページネーションとソートを組み合わせて指定することも可能

ID指定で1件取得

ID指定で1件取得は、GETでリクエストします。
URL : http://localhost:8080/api/items/(idを指定)

例. http://localhost:8080/api/items/1 (id=1のリソースを指定)

更新(PUT)

リソースの更新は、PUTでリクエストします。
URL : http://localhost:8080/api/items/(idを指定)

例. http://localhost:8080/api/items/1 (id=1のリソースを指定)

追加(POST)と同様に、リクエストボディに更新する情報をJSON形式で指定します。更新データは、サンプルソースの /WebAPI呼び出しフォルダにあります。(items-put.json)

{
  "name": "商品A",
  "price": 1800
}

部分更新(PATCH)

リソースの部分更新は、PATCHでリクエストします。
URL : http://localhost:8080/api/items/(idを指定)

例. http://localhost:8080/api/items/1 (id=1のリソースを指定)

リクエストボディに設定した部分のみが更新されます。

{
  "name": "商品A-1"
}
{
  "price": 1700
}

削除

リソースの削除は、DELETEでリクエストします。
URL : http://localhost:8080/api/items/(idを指定)

例. http://localhost:8080/api/items/1 (id=1のリソースを指定)

削除(DELETE)リクエストの場合、リクエストボディは不要です。

おわりに 今後の掲載記事予定

Spring Data REST で RESTful Webサービスを作る方法を紹介しましたが、いかがでしょうか?

今後、今回作成したアプリケーションに以下のような機能を拡張する方法を紹介する予定です。

  • Spring Data RESTで、Bean Validationによる入力検証を行う
  • Spring Data RESTで、条件検索に対応した一覧取得を行う
    • 商品名の部分一致検索とか、価格がいくら以下のものを検索など
  • Spring Data RESTで、関連したエンティティのデータも一括して取得する
  • 画像のアップロードに対応したRESTful Web APIを作成する

カサレアルでは、Springなどバックエンドアプリケーションの開発方法を学ぶコースを開催しています。

バックエンド開発を学ぶ研修一覧

 

--------------------------
開発支援・技術研修のご要望・ご相談はこちらから
--------------------------
【この技術ブログを読んだエンジニアの皆様へ】
カサレアルブログをお読みいただき、ありがとうございます!

私たちは、常に新しい技術に挑戦し、ユーザーのニーズに応えるサービスを提供しています。
もし、当社の技術への情熱や、会社・チーム・社員の雰囲気に共感いただけたなら、
ぜひ私たちと一緒に働きませんか?
現在、株式会社カサレアルでは事業拡大に伴い、新たな仲間となるエンジニアを積極的に募集しています。

少しでも興味をお持ちいただけましたら、まずは弊社のことを知っていただけると嬉しいです。
▼採用サイト
https://www.casareal.co.jp/recruit/career
▼社員インタビュー
https://hrmos.co/pages/casareal/jobs/0000016
▼エンジニアの仲間になる! エントリーはこちらから
https://hrmos.co/pages/casareal/jobs

皆様のエントリーを心よりお待ちしています!

[Java] 今から始めるレコードクラス

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です

コメント ※

名前 ※

メール ※

サイト