Spring Data REST API の自動生成 (JPA)

このガイドでは、ハイパーメディアベースRESTful (英語) フロントエンドを介してリレーショナル JPA データにアクセスするアプリケーションを作成するプロセスについて説明します。

構築するもの

Spring Data REST を使用して、データベースに格納されている Person オブジェクトを作成および取得できる Spring アプリケーションを構築します。Spring Data REST は Spring HATEOASSpring Data JPA の機能を取り入れ、自動的に組み合わせます。

Spring Data REST は、バックエンドデータストアとして Spring Data Neo4jSpring Data GemfireSpring Data MongoDB もサポートしますが、これらはこのガイドの一部ではありません。

必要なもの

このガイドを完了する方法

ほとんどの Spring 入門ガイドと同様に、最初から始めて各ステップを完了することも、このリポジトリ [GitHub] (英語) のコードを確認してソリューションに直接進むこともできます。

ローカル環境で最終結果を確認するには、次のいずれかを実行します。

Spring Initializr から開始

IDE を使用する場合はプロジェクト作成ウィザードを使用します。IDE を使用せずにコマンドラインなどで開発する場合は、この事前に初期化されたプロジェクトからプロジェクトを ZIP ファイルとしてダウンロードできます。このプロジェクトは、このチュートリアルの例に合うように構成されています。

プロジェクトを手動で初期化するには:

  1. IDE のメニューまたはブラウザーから Spring Initializr を開きます。アプリケーションに必要なすべての依存関係を取り込み、ほとんどのセットアップを行います。

  2. Gradle または Maven のいずれかと、使用する言語を選択します。このガイドは、Java を選択したことを前提としています。

  3. 依存関係をクリックし、Rest リポジトリSpring Data JPAH2 Database を選択します。

  4. 生成をクリックします。

  5. 結果の ZIP ファイルをダウンロードします。これは、選択して構成された Web アプリケーションのアーカイブです。

EclipseIntelliJ のような IDE は新規プロジェクト作成ウィザードから Spring Initializr の機能が使用できるため、手動での ZIP ファイルのダウンロードやインポートは不要です。
プロジェクトを Github からフォークして、IDE または他のエディターで開くこともできます。

ドメインオブジェクトを作成する

次のリスト(src/main/java/com/example/accessingdatarest/Person.java 内)が示すように、新しいドメインオブジェクトを作成して人を表示します。

package com.example.accessingdatarest;

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

@Entity
public class Person {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private long id;

  private String firstName;
  private String lastName;

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
}

Person オブジェクトには、名と姓があります。(また、自動生成されるように構成された ID オブジェクトもあるため、それに対処する必要はありません。)

Person リポジトリを作成する

次に、次のリスト(src/main/java/com/example/accessingdatarest/PersonRepository.java 内)が示すように、単純なリポジトリを作成する必要があります。

package com.example.accessingdatarest;

import java.util.List;

import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;

@RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long>, CrudRepository<Person,Long> {

  List<Person> findByLastName(@Param("name") String name);

}

このリポジトリは、Person オブジェクトに関連するさまざまな操作を実行できるインターフェースです。Spring Data Commons で定義されている PagingAndSortingRepository (Javadoc) インターフェースを継承することにより、これらの操作を取得します。

実行時に、Spring Data REST はこのインターフェースの実装を自動的に作成します。次に、@RepositoryRestResource (Javadoc) アノテーションを使用して、Spring MVC に /people で RESTful エンドポイントを作成するように指示します。

@RepositoryRestResource は、リポジトリのエクスポートには必要ありません。/persons のデフォルト値の代わりに /people を使用するなど、エクスポートの詳細を変更するためにのみ使用されます。

ここでは、lastName に基づいて Person オブジェクトのリストを取得するカスタムクエリも定義しました。このガイドの後半で呼び出す方法を確認できます。

Spring Boot は Spring Data JPA を自動的に起動して、PersonRepository の具体的な実装を作成し、JPA を使用してバックエンドインメモリデータベースと通信するように構成します。

Spring Data REST は Spring MVC 上に構築されます。Spring MVC コントローラー、JSON コンバーター、および RESTful フロントエンドを提供するその他の Bean のコレクションを作成します。これらのコンポーネントは、Spring Data JPA バックエンドにリンクします。Spring Boot を使用する場合、これはすべて自動構成されます。それがどのように機能するかを調べたい場合は、Spring Data REST の RepositoryRestMvcConfiguration を参照してください。

アプリケーションの実行

これで、AccessingDataRestApplication の main メソッドを実行してアプリケーションを実行できます。プログラムは IDE から実行することも、プロジェクトのルートディレクトリで次の Gradle コマンドを実行して実行することもできます。

./gradlew bootRun

あるいは、次のコマンドを使用して、Maven を使用してアプリケーションを実行することもできます。

./mvnw spring-boot:run

アプリケーションをテストする

アプリケーションが実行されたため、テストできます。任意の REST クライアントを使用できます。以下の例では、*nix ツール curl を使用しています。

最初に、トップレベルのサービスを見たいです。次の例は、その方法を示しています。

$ curl http://localhost:8080
{
  "_links" : {
    "people" : {
      "href" : "http://localhost:8080/people{?page,size,sort}",
      "templated" : true
    }
  }
}

前の例は、このサーバーが提供するものの最初の垣間見ることを提供します。http://localhost:8080/people に people リンクがあります。?page?size?sort などのいくつかのオプションがあります。

Spring Data REST は、JSON 出力に HAL フォーマット (英語) を使用します。これは柔軟性があり、提供されるデータに隣接するリンクを提供する便利な方法を提供します。

次の例は、人物レコードを表示する方法を示しています(現時点ではなし)。

$ curl http://localhost:8080/people
{
  "_embedded" : {
    "people" : []
  },
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/people{?page,size,sort}",
      "templated" : true
    },
    "search" : {
      "href" : "http://localhost:8080/people/search"
    }
  },
  "page" : {
    "size" : 20,
    "totalElements" : 0,
    "totalPages" : 0,
    "number" : 0
  }
}

現在、要素はないため、ページはありません。新しい Person を作成する時間です! 次のリストは、その方法を示しています。

$ curl -i -H "Content-Type:application/json" -d '{"firstName": "Frodo", "lastName": "Baggins"}' http://localhost:8080/people
HTTP/1.1 201 Created
Server: Apache-Coyote/1.1
Location: http://localhost:8080/people/1
Content-Length: 0
Date: Wed, 26 Feb 2014 20:26:55 GMT
  • -i: ヘッダーを含むレスポンスメッセージを確認できるようにします。新しく作成された Person の URI が表示されます。

  • -H "Content-Type:application/json": コンテンツ型を設定して、ペイロードが JSON オブジェクトを含むことをアプリケーションが認識できるようにします。

  • -d '{"firstName": "Frodo", "lastName": "Baggins"}': データが送信されています。

  • Windows を使用している場合、上記のコマンドは WSL で機能します。WSL をインストールできない場合は、一重引用符を二重引用符に置き換え、既存の二重引用符をエスケープする必要がある場合があります(例: -d "{\"firstName\": \"Frodo\", \"lastName\": \"Baggins\"}")。

POST 操作へのレスポンスに Location ヘッダーが含まれていることに注意してください。これには、新しく作成されたリソースの URI が含まれます。Spring Data REST には、作成されたばかりのリソースの表現をすぐに返すようにフレームワークを構成するために使用できる 2 つのメソッド (RepositoryRestConfiguration.setReturnBodyOnCreate(…) および setReturnBodyOnUpdate(…)) もあります。RepositoryRestConfiguration.setReturnBodyForPutAndPost(…) は、作成および更新操作の表現レスポンスを有効にするショートカットメソッドです。

次の例に示すように、すべての人を照会できます。

$ curl http://localhost:8080/people
{
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/people{?page,size,sort}",
      "templated" : true
    },
    "search" : {
      "href" : "http://localhost:8080/people/search"
    }
  },
  "_embedded" : {
    "people" : [ {
      "firstName" : "Frodo",
      "lastName" : "Baggins",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/people/1"
        }
      }
    } ]
  },
  "page" : {
    "size" : 20,
    "totalElements" : 1,
    "totalPages" : 1,
    "number" : 0
  }
}

people オブジェクトには、Frodo を含むリストが含まれています。self リンクがどのように含まれているかに注目してください。Spring Data REST は、グループ化のためにエンティティの名前を複数形にするために Evo Inflector (英語) も使用します。

次のように、個々のレコードを直接照会できます。

$ curl http://localhost:8080/people/1
{
  "firstName" : "Frodo",
  "lastName" : "Baggins",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/people/1"
    }
  }
}
これは、純粋に Web ベースのように見える場合があります。ただし、バックグラウンドでは、H2 リレーショナルデータベースがあります。本番環境では、おそらく PostgreSQL などの実際のものを使用します。
このガイドでは、ドメインオブジェクトは 1 つだけです。ドメインオブジェクトが互いに関連しているより複雑なシステムでは、Spring Data REST は接続されたレコードに移動するのに役立つ追加のリンクを表示します。

次の例に示すように、すべてのカスタムクエリを見つけることができます。

$ curl http://localhost:8080/people/search
{
  "_links" : {
    "findByLastName" : {
      "href" : "http://localhost:8080/people/search/findByLastName{?name}",
      "templated" : true
    }
  }
}

HTTP クエリパラメーター name を含む、クエリの URL を確認できます。これは、インターフェースに埋め込まれた @Param("name") アノテーションと一致することに注意してください。

次の例は、findByLastName クエリの使用方法を示しています。

$ curl http://localhost:8080/people/search/findByLastName?name=Baggins
{
  "_embedded" : {
    "persons" : [ {
      "firstName" : "Frodo",
      "lastName" : "Baggins",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/people/1"
        }
      }
    } ]
  }
}

コードで List<Person> を返すように定義しているため、すべての結果が返されます。Person のみを返すように定義していた場合、Person オブジェクトの 1 つを選択して返します。これは予測できないため、複数のエントリを返す可能性のあるクエリに対してはそうしたくないでしょう。

PUTPATCHDELETE REST 呼び出しを発行して、既存のレコードを(それぞれ)置換、更新、削除することもできます。次の例では、PUT 呼び出しを使用しています。

$ curl -X PUT -H "Content-Type:application/json" -d '{"firstName": "Bilbo", "lastName": "Baggins"}' http://localhost:8080/people/1
$ curl http://localhost:8080/people/1
{
  "firstName" : "Bilbo",
  "lastName" : "Baggins",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/people/1"
    }
  }
}

次の例では、PATCH 呼び出しを使用しています。

$ curl -X PATCH -H "Content-Type:application/json" -d '{"firstName": "Bilbo Jr."}' http://localhost:8080/people/1
$ curl http://localhost:8080/people/1
{
  "firstName" : "Bilbo Jr.",
  "lastName" : "Baggins",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/people/1"
    }
  }
}
PUT はレコード全体を置き換えます。指定されていないフィールドは null に置き換えられます。PATCH を使用して、アイテムのサブセットを更新できます。

次の例に示すように、レコードを削除することもできます。

$ curl -X DELETE http://localhost:8080/people/1
$ curl http://localhost:8080/people
{
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/people{?page,size,sort}",
      "templated" : true
    },
    "search" : {
      "href" : "http://localhost:8080/people/search"
    }
  },
  "page" : {
    "size" : 20,
    "totalElements" : 0,
    "totalPages" : 0,
    "number" : 0
  }
}

このハイパーメディア駆動型インターフェースの便利な側面は、curl(または任意の REST クライアント)を使用して、すべての RESTful エンドポイントを検出できることです。正式な契約書やインターフェースドキュメントを顧客と交換する必要はありません。

要約

おめでとう! ハイパーメディアベースの RESTful フロントエンドと JPA ベースのバックエンドを備えたアプリケーションを開発しました。

コードを入手する