Mengintegrasikan Spanner dengan Data Spring

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. Fiturnya 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 memudahkan penggunaan Spanner di aplikasi dan mengurangi jumlah kode yang perlu Anda tulis.

Halaman ini menjelaskan cara menambahkan Spring Data Spanner ke aplikasi Java. Untuk informasi selengkapnya tentang modul, 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 Anda. Dependensi ini menyediakan komponen Spring Data Spanner ke Spring ApplicationContext:

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

Data Spanner Model

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

Untuk setiap tabel dalam database, deklarasikan entity yang merepresentasikan record 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 entity dan tabel:

Anotasi entity
@Column(name = "columnName")

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

Jika Anda menghapus 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 disisipkan dengan baris saat ini.

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

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

@NotMapped

Menunjukkan bahwa properti tidak disimpan di 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 oleh entity. Setiap instance entity mewakili 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 detail tentang anotasi lain yang didukung modul.

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

  • Untuk entity Singer, contohnya menyertakan properti albums, dengan anotasi @Interleaved. Properti ini berisi daftar album yang disisipkan dengan entity Singer. Spring Data Spanner mengisi properti ini secara otomatis.
  • Untuk entity Album, contohnya 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 mencakup semua logika aplikasi yang membuat kueri dan mengubah data di Spanner.

Bagian berikut menjelaskan cara menggunakan SpannerTemplate dan SpannerRepository.

Mendapatkan kacang template

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

Contoh berikut menunjukkan class yang memperoleh dan menggunakan biji:

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 mencakup metode untuk menjalankan fungsi Java sebagai transaksi hanya baca dan transaksi baca-tulis. Untuk operasi tingkat yang lebih rendah, Anda bisa mendapatkan kacang 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, perbarui skema dengan pernyataan Data Definition Language (DDL), atau selesaikan tugas administratif lainnya, Anda dapat memperoleh kaca SpannerDatabaseAdminTemplate.

Menggunakan anotasi @Autowired untuk mendapatkan biji secara otomatis. Selanjutnya, Anda dapat menggunakan SpannerDatabaseAdminTemplate di seluruh kelas.

Contoh berikut menunjukkan class yang memperoleh dan menggunakan biji:

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