Integrare Spanner con Spring Data

Il modulo Spring Data Spanner ti consente di utilizzare Spanner in qualsiasi applicazione Java creata con il Spring Framework.

Come tutti i moduli Spring Data, Spring Data Spanner fornisce un modello di programmazione basato su Spring che mantiene le garanzie di coerenza e la scalabilità di Spanner. Le sue funzionalità sono simili a quelle di Spring Data JPA e Hibernate ORM, con annotazioni progettate per Spanner. Per saperne di più su come utilizzare Spring Data JPA con Spanner, consulta Integrare Spanner con Spring Data JPA (dialetto GoogleSQL).

Se hai già dimestichezza con Spring, Spring Data Spanner può aiutarti a utilizzare più facilmente Spanner nella tua applicazione e ridurre la quantità di codice da scrivere.

Questa pagina spiega come aggiungere Spring Data Spanner a un'applicazione Java. Per informazioni dettagliate sul modulo, consulta il riferimento di Spring Data Spanner.

Installa il modulo

Se utilizzi Maven, aggiungi la lista di materiali (BOM) di Spring Cloud GCP e Spring Data Spanner al file pom.xml. Queste dipendenze forniscono i componenti Spring Data Spanner a 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>

Devi anche creare un service account e utilizzare la chiave del account di servizio per autenticarti con Google Cloud.

Per ulteriori informazioni, consulta le istruzioni per la configurazione di un ambiente di sviluppo Java. Non è necessario installare la libreria client Google Cloud per Java; lo starter Spring Boot la installa automaticamente.

Configura il modulo

Questa sezione descrive alcune delle impostazioni di configurazione più utilizzate per Spring Data Spanner. Per un elenco completo delle impostazioni, consulta la documentazione di riferimento.

Specifica un'istanza e un database

Per specificare l'istanza e il database predefiniti, imposta le seguenti proprietà di configurazione per l'applicazione:

Proprietà Descrizione
spring.cloud.gcp.spanner.project-id Facoltativo. L'ID progetto Google Cloud . Sostituisce il valore di spring.cloud.gcp.config.project-id.
spring.cloud.gcp.spanner.instance-id L'ID istanza Spanner.
spring.cloud.gcp.spanner.database Il database a cui connettersi.

Modella i dati di Spanner

Con Spring Data Spanner, puoi utilizzare POJO (Plain Old Java Object) per modellare i dati archiviati nelle tabelle Spanner.

Per ogni tabella del database, dichiara un'entità che rappresenta un record in quella tabella. Utilizza le annotazioni per mappare l'entità e le relative proprietà a una tabella e alle sue colonne.

Puoi utilizzare le seguenti annotazioni per modellare relazioni semplici tra entità e tabelle:

Annotazioni delle entità
@Column(name = "columnName")

Facoltativo. Mappa la proprietà a una colonna specifica della tabella Spanner, sostituendo la strategia di denominazione che mappa automaticamente i nomi.

Se ometti questa proprietà, la strategia di denominazione predefinita per Spring Data Spanner mappa i nomi delle proprietà camelCase Java ai nomi delle colonne PascalCase. Ad esempio, la proprietà singerId viene associata al nome della colonna SingerId.

@Embedded

Indica che la proprietà è un oggetto incorporato che può contenere componenti di una chiave primaria. Se la proprietà viene effettivamente utilizzata nella chiave primaria, devi includere anche l'annotazione @PrimaryKey.

@Interleaved

@Interleaved(lazy = true)

Indica che una proprietà contiene un elenco di righe intercalate con la riga corrente.

Per impostazione predefinita, Spring Data Spanner recupera le righe interlacciate al momento della creazione dell'istanza. Per recuperare le righe in modo lazy, quando accedi alla proprietà, utilizza @Interleaved(lazy = true).

Esempio: se un'entità Singer può avere voci Album interlacciate come elementi secondari, aggiungi una proprietà List<Album> all'entità Singer. Aggiungi anche un'annotazione @Interleaved alla proprietà.

@NotMapped

Indica che una proprietà non è memorizzata nel database e deve essere ignorata.

@PrimaryKey

@PrimaryKey(keyOrder = N)

Indica che la proprietà è un componente della chiave primaria e identifica la posizione della proprietà all'interno della chiave primaria, a partire da 1. Il valore predefinito di keyOrder è 1.

Esempio: @PrimaryKey(keyOrder = 3)

@Table(name = "TABLE_NAME")

La tabella modellata dall'entità. Ogni istanza dell'entità rappresenta un record nella tabella. Sostituisci TABLE_NAME con il nome della tabella.

Esempio: @Table(name = "Singers")

Se devi modellare relazioni più complesse, consulta la documentazione di riferimento di Spring Data Spanner per informazioni dettagliate sulle altre annotazioni supportate dal modulo.

Gli esempi riportati di seguito mostrano un modo per modellare le tabelle Singers e Albums per Spring Data Spanner:

  • Per le entità Singer, l'esempio include una proprietà albums con un'annotazione @Interleaved. Questa proprietà contiene un elenco di album alternati con l'entità Singer. Spring Data Spanner compila automaticamente questa proprietà.
  • Per le entità Album, l'esempio include una proprietà relatedAlbums che non viene memorizzata in 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;
  }
}

Eseguire query e modificare i dati

Per eseguire query e modificare i dati con Spring Data Spanner, puoi acquisire un bean SpannerTemplate, che implementa SpannerOperations. SpannerTemplate fornisce metodi per eseguire query SQL e modificare i dati con istruzioni DML (Data Manipulation Language). Puoi anche utilizzare questo bean per accedere all'API di lettura e all'API di mutazione per Spanner.

Inoltre, puoi estendere l'interfaccia SpannerRepository per incapsulare tutta la logica di applicazione che esegue query e modifica i dati in Spanner.

Le sezioni seguenti spiegano come utilizzare SpannerTemplate e SpannerRepository.

Acquisisci un bean modello

Utilizza l'annotazione @Autowired per acquisire automaticamente un bean SpannerTemplate. Potrai quindi utilizzare SpannerTemplate per tutto il corso.

L'esempio seguente mostra una classe che acquisisce e utilizza il 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));
  }

}

Puoi utilizzare il bean SpannerTemplate per eseguire transazioni di sola lettura e transazioni di lettura/scrittura. Inoltre, puoi utilizzare l'annotazione @Transactional per creare transazioni declarative.

Acquisisci un bean del repository

Se utilizzi un SpannerRepository, puoi utilizzare l'annotazione @Autowired per acquisire un bean che implementa l'interfaccia del tuo repository. Un repository include metodi per l'esecuzione di funzioni Java come transazioni in sola lettura e transazioni di lettura/scrittura. Per le operazioni di livello inferiore, puoi recuperare il bean modello utilizzato dal repository.

Gli esempi seguenti mostrano l'interfaccia per un repository e una classe che acquisisce e utilizza il 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");
  }

}

Gestire Spanner

Per ottenere informazioni sui tuoi database Spanner, aggiornare uno schema con un'istruzione DDL (Data Definition Language) o completare altre attività amministrative, puoi acquisire un bean SpannerDatabaseAdminTemplate.

Utilizza l'annotazione @Autowired per acquisire automaticamente il bean. Puoi quindi utilizzare il SpannerDatabaseAdminTemplate per tutto il corso.

L'esempio seguente mostra una classe che acquisisce e utilizza il 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);
    }
  }
}

Passaggi successivi