Mengintegrasikan Spanner dengan Spring Data

Modul Spring Data Spanner membantu Anda menggunakan Spanner di aplikasi Java apa pun yang dibuat dengan Spring Framework.

Seperti semua modul Spring Data, Spring Data Spanner menyediakan model pemrograman berbasis Spring yang mempertahankan jaminan konsistensi dan skalabilitas Spanner. Fitur ini mirip dengan Spring Data JPA dan Hibernate ORM, dengan anotasi yang dirancang untuk Spanner. Untuk informasi selengkapnya tentang cara menggunakan Spring Data JPA dengan Spanner, lihat Mengintegrasikan Spanner dengan Spring Data JPA (dialek GoogleSQL).

Jika Anda sudah terbiasa dengan Spring, Spring Data Spanner dapat mempermudah penggunaan Spanner dalam aplikasi Anda dan mengurangi jumlah kode yang perlu Anda tulis.

Halaman ini menjelaskan cara menambahkan Spring Data Spanner ke aplikasi Java. Untuk mengetahui informasi mendetail tentang modul ini, lihat referensi Spring Data Spanner.

Menginstal modul

Jika Anda menggunakan Maven, tambahkan Bill of Materials (BOM) Spring Cloud GCP dan Spring Data Spanner ke file pom.xml. Dependensi ini menyediakan komponen Spring Data Spanner ke ApplicationContext Spring Anda:

<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>

Anda juga harus membuat akun layanan dan menggunakan kunci akun layanan untuk melakukan autentikasi dengan Google Cloud.

Untuk mengetahui informasi selengkapnya, lihat petunjuk untuk menyiapkan lingkungan pengembangan Java. Anda tidak perlu menginstal Library Klien Google Cloud untuk Java karena starter Spring Boot akan menginstal library klien secara otomatis.

Mengonfigurasi modul

Bagian ini menjelaskan beberapa setelan konfigurasi yang paling umum digunakan untuk Spring Data Spanner. Untuk mengetahui daftar lengkap setelan, lihat dokumentasi referensi.

Menentukan instance dan database

Untuk menentukan instance dan database default, tetapkan properti konfigurasi berikut untuk aplikasi Anda:

Properti Deskripsi
spring.cloud.gcp.spanner.project-id Opsional. ID Project Google Cloud. Mengganti nilai spring.cloud.gcp.config.project-id.
spring.cloud.gcp.spanner.instance-id ID instance Spanner.
spring.cloud.gcp.spanner.database Database yang akan dihubungkan.

Model data Spanner

Dengan Spring Data Spanner, Anda dapat menggunakan objek Java biasa (POJO) untuk membuat model data yang Anda simpan di tabel Spanner.

Untuk setiap tabel dalam database, deklarasikan entity yang mewakili data dalam tabel tersebut. Gunakan anotasi untuk memetakan entity dan propertinya ke tabel dan kolomnya.

Anda dapat menggunakan anotasi berikut untuk membuat model hubungan sederhana antara entitas dan tabel:

Anotasi entity
@Column(name = "columnName")

Opsional. Memetakan properti ke kolom tertentu dalam tabel Spanner, yang mengganti strategi penamaan yang otomatis memetakan nama.

Jika Anda menghilangkan properti ini, strategi penamaan default untuk Spring Data Spanner akan memetakan nama properti camelCase Java ke nama kolom PascalCase. Misalnya, properti singerId dipetakan ke nama kolom SingerId.

@Embedded

Menunjukkan bahwa properti adalah objek tersemat yang dapat menyimpan komponen kunci utama. Jika properti benar-benar digunakan dalam kunci utama, Anda juga harus menyertakan anotasi @PrimaryKey.

@Interleaved

@Interleaved(lazy = true)

Menunjukkan bahwa properti berisi daftar baris yang diselingi dengan baris saat ini.

Secara default, Spring Data Spanner mengambil baris yang diselingi saat pembuatan instance. Untuk mengambil baris secara lambat, saat Anda mengakses properti, gunakan @Interleaved(lazy = true).

Contoh: Jika entitas Singer dapat memiliki entri Album yang diselingi sebagai turunan, tambahkan properti List<Album> ke entitas Singer. Selain itu, tambahkan anotasi @Interleaved ke properti.

@NotMapped

Menunjukkan bahwa properti tidak disimpan dalam database dan harus diabaikan.

@PrimaryKey

@PrimaryKey(keyOrder = N)

Menunjukkan bahwa properti adalah komponen kunci utama, dan mengidentifikasi posisi properti dalam kunci utama, mulai dari 1. Default keyOrder adalah 1.

Contoh: @PrimaryKey(keyOrder = 3)

@Table(name = "TABLE_NAME")

Tabel yang dimodelkan entitas. Setiap instance entity mewakili kumpulan data dalam tabel. Ganti TABLE_NAME dengan nama tabel Anda.

Contoh: @Table(name = "Singers")

Jika Anda perlu membuat model hubungan yang lebih kompleks, lihat referensi Spring Data Spanner untuk mengetahui detail tentang anotasi lain yang didukung modul.

Contoh berikut menunjukkan satu cara untuk membuat model tabel Singers dan Albums untuk Spring Data Spanner:

  • Untuk entitas Singer, contoh menyertakan properti albums, dengan anotasi @Interleaved. Properti ini berisi daftar album yang diselingi dengan entity Singer. Spring Data Spanner mengisi properti ini secara otomatis.
  • Untuk entity Album, contoh menyertakan properti relatedAlbums yang tidak disimpan di Spanner.
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;
  }
}

Membuat kueri dan mengubah data

Untuk membuat kueri dan mengubah data dengan Spring Data Spanner, Anda dapat memperoleh bean SpannerTemplate, yang mengimplementasikan SpannerOperations. SpannerTemplate menyediakan metode untuk menjalankan kueri SQL dan mengubah data dengan pernyataan Bahasa Manipulasi Data (DML). Anda juga dapat menggunakan bean ini untuk mengakses read API dan mutation API untuk Spanner.

Selain itu, Anda dapat memperluas antarmuka SpannerRepository untuk mengenkapsulasi semua logika aplikasi yang membuat kueri dan mengubah data di Spanner.

Bagian berikut menjelaskan cara menggunakan SpannerTemplate dan SpannerRepository.

Mendapatkan bean template

Gunakan anotasi @Autowired untuk mendapatkan bean SpannerTemplate secara otomatis. Kemudian, Anda dapat menggunakan SpannerTemplate di seluruh class.

Contoh berikut menunjukkan class yang memperoleh dan menggunakan 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.
    List<Singer> allSingers = this.spannerTemplate
        .query(Singer.class, Statement.of("SELECT * FROM Singers"),
                new SpannerQueryOptions().setAllowPartialRead(true));
  }

}

Anda dapat menggunakan bean SpannerTemplate untuk menjalankan transaksi hanya baca dan transaksi baca-tulis. Selain itu, Anda dapat menggunakan anotasi @Transactional untuk membuat transaksi deklaratif.

Mendapatkan bean repositori

Jika menggunakan SpannerRepository, Anda dapat menggunakan anotasi @Autowired untuk mendapatkan bean yang mengimplementasikan antarmuka repositori Anda. Repositori menyertakan metode untuk menjalankan fungsi Java sebagai transaksi hanya baca dan transaksi baca-tulis. Untuk operasi tingkat rendah, Anda dapat mendapatkan bean template yang digunakan repositori.

Contoh berikut menunjukkan antarmuka untuk repositori dan class yang mendapatkan dan menggunakan bean:

import com.google.cloud.spanner.Key;
import com.google.cloud.spring.data.spanner.repository.SpannerRepository;
import com.google.cloud.spring.data.spanner.repository.query.Query;
import java.util.List;
import org.springframework.data.repository.query.Param;


/**
 * An interface of various Query Methods. The behavior of the queries is defined only by
 * their names, arguments, or annotated SQL strings. The implementation of these functions
 * is generated by Spring Data Cloud Spanner.
 */
public interface SingerRepository extends SpannerRepository<Singer, Key> {
  List<Singer> findByLastName(String lastName);

  int countByFirstName(String firstName);

  int deleteByLastName(String lastName);

  List<Singer> findTop3DistinctByFirstNameAndSingerIdIgnoreCaseOrLastNameOrderByLastNameDesc(
      String firstName, String lastName, long singerId);

  @Query("SELECT * FROM Singers WHERE firstName LIKE '%@fragment';")
  List<Singer> getByQuery(@Param("fragment") String firstNameFragment);
}
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 a SpannerRepository to execute read-write queries
 * generated from interface definitions.
 *
 */
@Component
public class SpannerRepositorySample {

  @Autowired
  SingerRepository singerRepository;

  public void runRepositoryExample() {
    List<Singer> lastNameSingers = this.singerRepository.findByLastName("a last name");

    int fistNameCount = this.singerRepository.countByFirstName("a first name");

    int deletedLastNameCount = this.singerRepository.deleteByLastName("a last name");
  }

}

Mengelola Spanner

Untuk mendapatkan informasi tentang database Spanner, memperbarui skema dengan pernyataan Bahasa Definisi Data (DDL), atau menyelesaikan tugas administrative lainnya, Anda dapat memperoleh bean SpannerDatabaseAdminTemplate.

Gunakan anotasi @Autowired untuk mendapatkan bean secara otomatis. Kemudian, Anda dapat menggunakan SpannerDatabaseAdminTemplate di seluruh class.

Contoh berikut menunjukkan class yang memperoleh dan menggunakan bean:

import com.google.cloud.spring.data.spanner.core.admin.SpannerDatabaseAdminTemplate;
import com.google.cloud.spring.data.spanner.core.admin.SpannerSchemaUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * This sample demonstrates how to generate schemas for interleaved tables from POJOs and how to
 * execute DDL.
 */
@Component
public class SpannerSchemaToolsSample {

  @Autowired
  SpannerDatabaseAdminTemplate spannerDatabaseAdminTemplate;

  @Autowired
  SpannerSchemaUtils spannerSchemaUtils;

  /**
   * Creates the Singers table. Also creates the Albums table, because Albums is interleaved with
   * Singers.
   */
  public void createTableIfNotExists() {
    if (!this.spannerDatabaseAdminTemplate.tableExists("Singers")) {
      this.spannerDatabaseAdminTemplate.executeDdlStrings(
          this.spannerSchemaUtils
              .getCreateTableDdlStringsForInterleavedHierarchy(Singer.class),
          true);
    }
  }

  /**
   * Drops both the Singers and Albums tables using just a reference to the Singer entity type ,
   * because they are interleaved.
   */
  public void dropTables() {
    if (this.spannerDatabaseAdminTemplate.tableExists("Singers")) {
      this.spannerDatabaseAdminTemplate.executeDdlStrings(
          this.spannerSchemaUtils.getDropTableDdlStringsForInterleavedHierarchy(Singer.class),
          false);
    }
  }
}

Langkah selanjutnya