Spanner と Spring Data を統合する

Spring Data Spanner モジュールは、Spring Framework で構築された Java アプリケーションで Spanner を使用する場合に役立ちます。

すべての Spring Data モジュールと同様に、Spring Data Spanner では Spanner の整合性の保証とスケーラビリティを保持する Spring ベースのプログラミング モデルが提供されます。その機能は、Spanner 用に設計されたアノテーションを使用した Spring Data JPAHibernate ORM に似ています。Spanner で Spring Data JPA を使用する方法について詳しくは、Spanner を Spring Data JPA(GoogleSQL 言語)と統合するをご覧ください。

Spring についてすでに習熟している場合、Spring Data Spanner を使用すると、アプリケーションで Spanner を使いやすくなり、作成する必要があるコードの量を減らすことができます。

このページでは、Spring Data Spanner を Java アプリケーションに追加する方法について説明します。モジュールの詳細については、Spring Data Spanner リファレンスをご覧ください。

モジュールをインストールする

Maven を使用する場合は、Spring Cloud GCP の部品表(BOM)と Spring Data Spanner を pom.xml ファイルに追加します。これらの依存関係によって、Spring ApplicationContext に Spring Data Spanner コンポーネントが提供されます。

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>spring-cloud-gcp-dependencies</artifactId>
      <version>3.7.7</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>${spring.boot.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>spring-cloud-gcp-starter-data-spanner</artifactId>
  </dependency>
</dependencies>

また、サービス アカウントを作成し、サービス アカウント キーを使用して Google Cloudで認証する必要があります。

詳細については、Java 開発環境の設定の手順をご覧ください。Java 用 Google Cloud クライアント ライブラリをインストールする必要はありません。Spring Boot スターターによってクライアント ライブラリが自動的にインストールされます。

モジュールの設定

このセクションでは、Spring Data Spanner のよく使用されるいくつかの構成設定について説明します。設定の完全なリストについては、リファレンス ドキュメントをご覧ください。

インスタンスとデータベースを指定する

デフォルトのインスタンスとデータベースを指定するには、アプリケーションの次の構成プロパティを設定します。

プロパティ 説明
spring.cloud.gcp.spanner.project-id 省略可。 Google Cloud プロジェクト IDspring.cloud.gcp.config.project-id の値をオーバーライドします。
spring.cloud.gcp.spanner.instance-id Spanner インスタンス ID
spring.cloud.gcp.spanner.database 接続先のデータベース。

Spanner データをモデリングする

Spring Data Spanner では、POJO(Plain Old Java Object)を使用して Spanner テーブルに格納するデータをモデリングできます。

データベースの各テーブルに対して、そのテーブル内のレコードを表すエンティティを宣言します。アノテーションを使用して、エンティティとそのプロパティをテーブルとその列にマッピングします。

次のアノテーションを使用して、エンティティとテーブルとのシンプルな関係をモデリングできます。

エンティティ アノテーション
@Column(name = "columnName")

省略可。Spanner テーブルの特定の列にプロパティをマッピングし、名前を自動的にマッピングする命名方法をオーバーライドします。

このプロパティを省略した場合、Spring Data Spanner のデフォルトの命名方法では、Java の camelCase プロパティ名が PascalCase 列名にマッピングされます。たとえば、プロパティ singerId は列名 SingerId にマッピングされます。

@Embedded

プロパティが、主キーのコンポーネントを保持できる埋め込みオブジェクトであることを示します。プロパティを主キーで実際に使用する場合、@PrimaryKey アノテーションも含める必要があります。

@Interleaved

@Interleaved(lazy = true)

プロパティに、現在の行でインターリーブされる行の一覧が含まれていることを示します。

デフォルトでは、Spring Data Spanner はインスタンス作成時にインターリーブされた行をフェッチします。行を必要に応じてフェッチするには、プロパティにアクセスする際に @Interleaved(lazy = true) を使用します。

例: Singer エンティティが Album エントリを子としてインターリーブできた場合、List<Album> プロパティを Singer エンティティに追加します。さらに、@Interleaved アノテーションをプロパティに追加します。

@NotMapped

プロパティがデータベースに保存されず、無視されることを示します。

@PrimaryKey

@PrimaryKey(keyOrder = N)

プロパティが主キーのコンポーネントであり、1 から始まる主キー内のプロパティの位置を示します。デフォルトの keyOrder1 です。

例: @PrimaryKey(keyOrder = 3)

@Table(name = "TABLE_NAME")

エンティティによってモデリングされるテーブル。エンティティの各インスタンスは、テーブル内のレコードを表します。TABLE_NAME をテーブルの名前に置換します。

例: @Table(name = "Singers")

より複雑な関係をモデリングする必要がある場合は、モジュールがサポートするその他のアノテーションの詳細について、Spring Data Spanner リファレンスをご覧ください。

以下は、Spring Data Spanner の Singers テーブルと Albums テーブルをモデリングする方法の一例です。

  • Singer エンティティの場合、この例では、@Interleaved アノテーションを使用した albums プロパティが含まれます。このプロパティには、Singer エンティティによってインターリーブされるアルバムの一覧が含まれます。Spring Data Spanner では、このプロパティに自動的に値が設定されます。
  • Album エンティティの場合、この例には Spanner に保存されていない relatedAlbums プロパティが含まれます。
import com.google.cloud.spring.data.spanner.core.mapping.Interleaved;
import com.google.cloud.spring.data.spanner.core.mapping.PrimaryKey;
import com.google.cloud.spring.data.spanner.core.mapping.Table;
import java.util.Date;
import java.util.List;


/**
 * An entity and table holding singers.
 */
@Table(name = "Singers")
public class Singer {
  @PrimaryKey
  long singerId;

  String firstName;

  String lastName;

  Date birthDate;

  @Interleaved
  List<Album> albums;
}
import com.google.cloud.spring.data.spanner.core.mapping.NotMapped;
import com.google.cloud.spring.data.spanner.core.mapping.PrimaryKey;
import com.google.cloud.spring.data.spanner.core.mapping.Table;
import java.util.List;

/**
 * An entity class representing an Album.
 */
@Table(name = "Albums")
public class Album {

  @PrimaryKey
  long singerId;

  @PrimaryKey(keyOrder = 2)
  long albumId;

  String albumTitle;

  long marketingBudget;

  @NotMapped
  List<Album> relatedAlbums;

  public Album(long singerId, long albumId, String albumTitle, long marketingBudget) {
    this.singerId = singerId;
    this.albumId = albumId;
    this.albumTitle = albumTitle;
    this.marketingBudget = marketingBudget;
  }
}

データのクエリと変更

Spring Data Spanner を使用してデータをクエリおよび変更するには、SpannerTemplate Bean を取得できます。これは、SpannerOperations を実装します。SpannerTemplate は、データ操作言語(DML)ステートメントによって、SQL クエリを実行し、データを変更する方法を提供します。この Bean を使用して、Spanner の読み取り APIMutation API にアクセスすることもできます。

また、SpannerRepository インターフェースを拡張し、Spanner でデータをクエリおよび変更するすべてのアプリケーション ロジックをカプセル化できます。

次のセクションでは、SpannerTemplateSpannerRepository の操作方法を説明します。

テンプレート Bean を取得する

@Autowired アノテーションを使用して、SpannerTemplate Bean を自動的に取得します。その後、クラス全体で SpannerTemplate を使用できます。

次の例は、Bean を取得して使用するクラスを示しています。

import com.google.cloud.spanner.KeySet;
import com.google.cloud.spanner.Statement;
import com.google.cloud.spring.data.spanner.core.SpannerQueryOptions;
import com.google.cloud.spring.data.spanner.core.SpannerTemplate;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * A quick start code for Spring Data Cloud Spanner. It demonstrates how to use SpannerTemplate to
 * execute DML and SQL queries, save POJOs, and read entities.
 */
@Component
public class SpannerTemplateSample {

  @Autowired
  SpannerTemplate spannerTemplate;

  public void runTemplateExample(Singer singer) {
    // Delete all of the rows in the Singer table.
    this.spannerTemplate.delete(Singer.class, KeySet.all());

    // Insert a singer into the Singers table.
    this.spannerTemplate.insert(singer);

    // Read all of the singers in the Singers table.