Cloud Spanner ที่มี ORM ของ Hibernate

1. ภาพรวม

Hibernate กลายเป็นโซลูชัน ORM มาตรฐานโดยพฤตินัยสำหรับโปรเจ็กต์ Java โดยรองรับฐานข้อมูลเชิงสัมพันธ์หลักๆ ทั้งหมด และเปิดใช้เครื่องมือ ORM ที่มีประสิทธิภาพมากยิ่งขึ้น เช่น Spring Data JPA นอกจากนี้ ยังมีเฟรมเวิร์กที่เข้ากันได้กับ Hibernate มากมาย เช่น Spring Boot, Microprofile และ Quarkus

Cloud Spanner Dialect สำหรับ Hibernate ORM ช่วยให้ใช้ Hibernate กับ Cloud Spanner ได้ คุณจะได้รับประโยชน์จาก Cloud Spanner ซึ่งก็คือความสามารถในการปรับขนาดและความหมายเชิงสัมพันธ์ พร้อมด้วยการคงอยู่ของข้อมูลตามรูปแบบของ Hibernate ซึ่งจะช่วยคุณย้ายข้อมูลแอปพลิเคชันที่มีอยู่ไปยังระบบคลาวด์ หรือเขียนแอปพลิเคชันใหม่โดยใช้ประโยชน์จากประสิทธิภาพการทำงานของนักพัฒนาแอปที่เพิ่มขึ้นจากเทคโนโลยีที่ใช้ Hibernate

สิ่งที่คุณจะได้เรียนรู้

  • วิธีเขียนแอปพลิเคชัน Hibernate อย่างง่ายที่เชื่อมต่อกับ Cloud Spanner
  • วิธีสร้างฐานข้อมูล Cloud Spanner
  • วิธีใช้ Cloud Spanner Dialect สำหรับ Hibernate ORM
  • วิธีใช้การดำเนินการสร้าง-อ่าน-อัปเดต-ลบ (CRUD) กับ Hibernate

สิ่งที่คุณต้องมี

  • โปรเจ็กต์ Google Cloud Platform
  • เบราว์เซอร์ เช่น Chrome หรือ Firefox

2. การตั้งค่าและข้อกำหนด

การตั้งค่าสภาพแวดล้อมแบบเรียนรู้ด้วยตนเอง

  1. ลงชื่อเข้าใช้ Cloud Console และสร้างโปรเจ็กต์ใหม่หรือใช้โปรเจ็กต์ที่มีอยู่ (หากยังไม่มีบัญชี Gmail หรือ G Suite คุณต้อง สร้างบัญชี)

k6ai2NRmxIjV5iMFlVgA_ZyAWE4fhRrkrZZ5mZuCas81YLgk0iwIyvgoDet4s2lMYGC5K3xLSOjIbmC9kjiezvQuxuhdYRolbv1rft1lOmA_P2U3OYcaAzN9JgP-Ncm18i5qgf9LzAUtcCMcSYtCOrEWuILx3XBwb3GILPqXDd6cJiQQxmylg8GNftqlnE7u8aJLhlr1ZLRkpncKdj8ERnqcH71wab2HlfUnO9CgXKd0-CAQC2t3CH0kuQRxdtP0ws43t5-O2d4d0WXDUfawKoK3nfWQ73s_x4QI69xqzqdDR4tUuNmrv4FC9Yq8vtK5IVm49h_8h6x9X281hAcJcOFDtX7g2BXPvP5O7SOR2V4UI6W8gN6cTJCVAdtWHRrS89zH-qWE0IQdjFpOs_8T-s4vQCXA6w

จดจำรหัสโปรเจ็กต์ ซึ่งเป็นชื่อที่ไม่ซ้ำกันในโปรเจ็กต์ Google Cloud ทั้งหมด (ชื่อด้านบนมีผู้ใช้แล้วและคุณจะใช้ไม่ได้ ขออภัย) เราจะอ้างอิงรหัสนี้ใน Codelab นี้ในภายหลังเป็น PROJECT_ID

  1. จากนั้นคุณจะต้อง เปิดใช้การเรียกเก็บเงิน ใน Cloud Console เพื่อใช้ทรัพยากร Google Cloud

การทำตาม Codelab นี้ไม่ควรมีค่าใช้จ่ายมากนัก หรืออาจไม่มีค่าใช้จ่ายเลย โปรดทำตามวิธีการในส่วน "การล้างข้อมูล" ซึ่งจะแนะนำวิธีปิดทรัพยากรเพื่อไม่ให้มีการเรียกเก็บเงินนอกเหนือจากบทแนะนำนี้ ผู้ใช้ใหม่ของ Google Cloud มีสิทธิ์เข้าร่วมโปรแกรม ทดลองใช้ฟรี$300 USD

เปิดใช้งาน Cloud Shell

  1. จาก Cloud Console ให้คลิก เปิดใช้งาน Cloud Shell R47NpBm6yyzso5vnxnRBikeDAXxl3LsM6tip3rJxnKuS2EZdCI0h-eIOGm9aECq8JXbMFlJkd68uTutXU8gGmQUVa5iI1OdZczXP2tzqZ_mj0pR4sZ8eSwOwUlWADR7ARCqrMTQPQA

STsYbcAtkIQyN6nL9BJhld3Fv5KxedYynpUVcRWwvIR-sYMMc4kfK-unIYgtsD4P6T0P8z-A12388tPmAh-Trsx80qobaW4KQXHJ7qJI6rwm762LrxurYbxwiDG-v_HiUYsWnXMciw

หากไม่เคยเริ่มใช้ Cloud Shell มาก่อน คุณจะเห็นหน้าจอระดับกลาง (ครึ่งหน้าล่าง) ที่อธิบายว่า Cloud Shell คืออะไร ในกรณีนี้ ให้คลิกต่อไป (และคุณจะไม่เห็นหน้าจอนี้อีก) หน้าจอที่แสดงเพียงครั้งเดียวจะมีลักษณะดังนี้

LnGMTn1ObgwWFtWpjSdzlA9TDvSbcY76GiLQLc_f7RP1QBK1Tl4H6kLCHzsi89Lkc-serOpqNH-F2XKmV5AnBqTbPon4HvCwSSrY_ERFHzeYmK1lnTfr-6x5eVoaHpRSrCUrolXUPQ

การจัดสรรและเชื่อมต่อกับ Cloud Shell จะใช้เวลาไม่นาน

hfu9bVHmrWw01Hnrlf4MBNja6yvssDnZzN9oupcG12PU88Vvo30tTluX9IySwnu5_TG3U2UXAasX9eCwqwZtc6Yhwxri95zG82DLUcKxrFYaXnVd7OqVoU6zanoZa0PtvubjLLHxnA

เครื่องเสมือนนี้โหลดเครื่องมือพัฒนาทั้งหมดที่คุณต้องการ โดยมีไดเรกทอรีแรกขนาด 5 GB ที่คงอยู่และทำงานใน Google Cloud ซึ่งช่วยเพิ่มประสิทธิภาพเครือข่ายและการตรวจสอบสิทธิ์ได้อย่างมาก คุณสามารถทำงานส่วนใหญ่หรือทั้งหมดใน Codelab นี้ได้โดยใช้เพียงเบราว์เซอร์หรือ Chromebook

เมื่อเชื่อมต่อกับ Cloud Shell แล้ว คุณควรจะเห็นว่าคุณได้รับการตรวจสอบสิทธิ์แล้วและโปรเจ็กต์ตั้งค่าเป็นรหัสโปรเจ็กต์ของคุณแล้ว

  1. เรียกใช้คำสั่งต่อไปนี้ใน Cloud Shell เพื่อยืนยันว่าคุณได้รับการตรวจสอบสิทธิ์แล้ว
gcloud auth list

เอาต์พุตจากคำสั่ง

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
gcloud config list project

เอาต์พุตจากคำสั่ง

[core]
project = <PROJECT_ID>

หากไม่เป็นเช่นนั้น คุณสามารถตั้งค่าได้ด้วยคำสั่งนี้

gcloud config set project <PROJECT_ID>

เอาต์พุตจากคำสั่ง

Updated property [core/project].

3. สร้างฐานข้อมูล

หลังจากเปิดใช้ Cloud Shell แล้ว คุณจะเริ่มใช้ gcloud เพื่อโต้ตอบกับโปรเจ็กต์ GCP ได้

ขั้นแรก ให้เปิดใช้ Cloud Spanner API

gcloud services enable spanner.googleapis.com

ตอนนี้มาสร้างอินสแตนซ์ Cloud Spanner ที่ชื่อว่า codelab-instance กัน

gcloud spanner instances create codelab-instance \
 --config=regional-us-central1 \
 --description="Codelab Instance" --nodes=1

ตอนนี้เราต้องเพิ่มฐานข้อมูลลงในอินสแตนซ์นี้ เราจะตั้งชื่อฐานข้อมูลว่า codelab-db

gcloud spanner databases create codelab-db --instance=codelab-instance

4. สร้างแอปเปล่า

เราจะใช้ Maven Quickstart Archetype เพื่อสร้างแอปพลิเคชันคอนโซล Java อย่างง่าย

mvn archetype:generate \
 -DgroupId=codelab \
 -DartifactId=spanner-hibernate-codelab \
 -DarchetypeArtifactId=maven-archetype-quickstart \
 -DarchetypeVersion=1.4 \
 -DinteractiveMode=false

เปลี่ยนไปใช้ไดเรกทอรีแอป

cd spanner-hibernate-codelab

คอมไพล์และเรียกใช้แอปโดยใช้ Maven

mvn compile exec:java -Dexec.mainClass=codelab.App

คุณควรเห็นข้อความ Hello World! พิมพ์ในคอนโซล

5. เพิ่มทรัพยากร Dependency

มาสำรวจซอร์สโค้ดโดยเปิด Cloud Shell Editor และเรียกดูภายในไดเรกทอรี spanner-hibernate-codelab กัน

b5cb37d043d4d2b0.png

ตอนนี้เรามีเพียงแอปคอนโซล Java พื้นฐานที่พิมพ์ "Hello World!" แต่สิ่งที่เราต้องการจริงๆ คือการเขียนแอปพลิเคชัน Java ที่ใช้ Hibernate เพื่อสื่อสารกับ Cloud Spanner ซึ่งเราจะต้องใช้ Cloud Spanner Dialect สำหรับ Hibernate, ไดรเวอร์ Cloud Spanner JDBC และ Hibernate Core ดังนั้น มาเพิ่มทรัพยากร Dependency ต่อไปนี้ลงในบล็อก <dependencies> ภายในไฟล์ pom.xml กัน

pom.xml

    <!-- Spanner Dialect -->
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-spanner-hibernate-dialect</artifactId>
      <version>1.5.0</version>
    </dependency>

    <!-- JDBC Driver -->
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-spanner-jdbc</artifactId>
      <version>2.0.0</version>
    </dependency>

    <!-- Hibernate -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>5.4.29.Final</version>
    </dependency>

6. กำหนดค่า Hibernate ORM

จากนั้นเราจะสร้างไฟล์การกำหนดค่า Hibernate hibernate.cfg.xml และ hibernate.properties เรียกใช้คำสั่งต่อไปนี้เพื่อสร้างไฟล์เปล่า แล้วแก้ไขไฟล์โดยใช้ Cloud Shell Editor

mkdir src/main/resources \
 && touch src/main/resources/hibernate.cfg.xml \
 && touch src/main/resources/hibernate.properties

มาบอก Hibernate เกี่ยวกับคลาสเอนทิตีที่มีคำอธิบายประกอบที่เราจะแมปกับฐานข้อมูลโดยกรอกข้อมูลใน hibernate.cfg.xml กัน (เราจะสร้างคลาสเอนทิตีในภายหลัง)

src/main/resources/hibernate.cfg.xml

<hibernate-configuration>
  <session-factory>
    <!-- Annotated entity classes -->
    <mapping class="codelab.Album"/>
    <mapping class="codelab.Singer"/>
  </session-factory>
</hibernate-configuration>

นอกจากนี้ Hibernate ยังต้องทราบวิธีเชื่อมต่อกับอินสแตนซ์ Cloud Spanner และ Dialect ที่จะใช้ ดังนั้น เราจะบอกให้ใช้ SpannerDialect สำหรับไวยากรณ์ SQL, ไดรเวอร์ Spanner JDBC และสตริงการเชื่อมต่อ JDBC ที่มีพิกัดฐานข้อมูล ซึ่งจะอยู่ในไฟล์ hibernate.properties

src/main/resources/hibernate.properties

hibernate.dialect=com.google.cloud.spanner.hibernate.SpannerDialect
hibernate.connection.driver_class=com.google.cloud.spanner.jdbc.JdbcDriver
hibernate.connection.url=jdbc:cloudspanner:/projects/{PROJECT_ID}/instances/codelab-instance/databases/codelab-db
# auto-create or update DB schema
hibernate.hbm2ddl.auto=update
hibernate.show_sql=true

อย่าลืมแทนที่ {PROJECT_ID} ด้วยรหัสโปรเจ็กต์ของคุณ ซึ่งคุณดูได้โดยเรียกใช้คำสั่งต่อไปนี้

gcloud config get-value project

เนื่องจากเราไม่มีสคีมาฐานข้อมูลที่มีอยู่ เราจึงเพิ่มพร็อพเพอร์ตี้ hibernate.hbm2ddl.auto=update เพื่อให้ Hibernate สร้างตาราง 2 ตารางใน Cloud Spanner เมื่อเราเรียกใช้แอปเป็นครั้งแรก

โดยปกติแล้ว คุณจะต้องตรวจสอบว่าได้ตั้งค่าข้อมูลเข้าสู่ระบบการตรวจสอบสิทธิ์แล้ว โดยใช้ไฟล์ JSON ของบัญชีบริการในตัวแปรสภาพแวดล้อม GOOGLE_APPLICATION_CREDENTIALS หรือข้อมูลเข้าสู่ระบบเริ่มต้นของแอปพลิเคชันที่กำหนดค่าโดยใช้คำสั่ง gcloud auth application-default login อย่างไรก็ตาม เนื่องจากเรากำลังเรียกใช้ใน Cloud Shell ระบบจึงตั้งค่าข้อมูลเข้าสู่ระบบเริ่มต้นของโปรเจ็กต์ไว้แล้ว

7. สร้างคลาสเอนทิตีที่มีคำอธิบายประกอบ

ตอนนี้เราพร้อมที่จะเขียนโค้ดแล้ว

เราจะกำหนดออบเจ็กต์ Java ธรรมดา 2 รายการ (POJO) ที่จะแมปกับตารางใน Cloud Spanner ได้แก่ Singer และ Album Album จะมีความสัมพันธ์แบบ @ManyToOne กับ Singer เรายังแมป Singer กับรายการ Album ของนักร้องได้ด้วยคำอธิบายประกอบ @OneToMany แต่สำหรับตัวอย่างนี้ เราไม่ต้องการโหลดอัลบั้มทั้งหมดทุกครั้งที่ต้องดึงนักร้องจากฐานข้อมูล

เพิ่มคลาสเอนทิตี Singer และ Album

สร้างไฟล์คลาส

touch src/main/java/codelab/Singer.java \
&& touch src/main/java/codelab/Album.java

วางเนื้อหาของไฟล์

src/main/java/codelab/Singer.java

package codelab;

import java.util.Date;
import java.util.UUID;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.hibernate.annotations.Type;

@Entity
public class Singer {

  @Id
  @GeneratedValue
  @Type(type = "uuid-char")
  private UUID singerId;

  private String firstName;

  private String lastName;

  @Temporal(TemporalType.DATE)
  private Date birthDate;

  public Singer() {
  }

  public Singer(String firstName, String lastName, Date birthDate) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.birthDate = birthDate;
  }

  public UUID getSingerId() {
    return singerId;
  }

  public void setSingerId(UUID singerId) {
    this.singerId = singerId;
  }

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

  public Date getBirthDate() {
    return birthDate;
  }

  public void setBirthDate(Date birthDate) {
    this.birthDate = birthDate;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof Singer)) {
      return false;
    }

    Singer singer = (Singer) o;

    if (!firstName.equals(singer.firstName)) {
      return false;
    }
    if (!lastName.equals(singer.lastName)) {
      return false;
    }
    return birthDate.equals(singer.birthDate);
  }

  @Override
  public int hashCode() {
    int result = firstName.hashCode();
    result = 31 * result + lastName.hashCode();
    result = 31 * result + birthDate.hashCode();
    return result;
  }
}

src/main/java/codelab/Album.java

package codelab;

import java.util.UUID;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import org.hibernate.annotations.Type;

@Entity
public class Album {

  @Id
  @GeneratedValue
  @Type(type = "uuid-char")
  UUID albumId;

  @ManyToOne
  Singer singer;

  String albumTitle;

  public Album() {
  }

  public Album(Singer singer, String albumTitle) {
    this.singer = singer;
    this.albumTitle = albumTitle;
  }

  public UUID getAlbumId() {
    return albumId;
  }

  public void setAlbumId(UUID albumId) {
    this.albumId = albumId;
  }

  public Singer getSinger() {
    return singer;
  }

  public void setSinger(Singer singer) {
    this.singer = singer;
  }

  public String getAlbumTitle() {
    return albumTitle;
  }

  public void setAlbumTitle(String albumTitle) {
    this.albumTitle = albumTitle;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof Album)) {
      return false;
    }

    Album album = (Album) o;

    if (!singer.equals(album.singer)) {
      return false;
    }
    return albumTitle.equals(album.albumTitle);
  }

  @Override
  public int hashCode() {
    int result = singer.hashCode();
    result = 31 * result + albumTitle.hashCode();
    return result;
  }
}

โปรดสังเกตว่าสำหรับตัวอย่างนี้ เราใช้ UUID ที่สร้างขึ้นโดยอัตโนมัติสำหรับคีย์หลัก ซึ่งเป็นประเภทรหัสที่แนะนำใน Cloud Spanner เนื่องจากช่วยหลีกเลี่ยงฮอตสปอตได้เมื่อระบบแบ่งข้อมูลระหว่างเซิร์ฟเวอร์ตามช่วงคีย์ คีย์จำนวนเต็มที่เพิ่มขึ้นแบบโมโนโทนิกก็ใช้ได้เช่นกัน แต่ประสิทธิภาพอาจต่ำกว่า

8. บันทึกและค้นหาเอนทิตี

เมื่อกำหนดค่าทุกอย่างและกำหนดออบเจ็กต์เอนทิตีแล้ว เราจะเริ่มเขียนลงในฐานข้อมูลและค้นหาฐานข้อมูลได้ เราจะเปิด Session ของ Hibernate แล้วใช้เพื่อลบแถวตารางทั้งหมดในเมธอด clearData() ก่อน จากนั้นบันทึกเอนทิตีบางรายการในเมธอด writeData() และเรียกใช้การค้นหาบางรายการโดยใช้ภาษาการค้นหาของ Hibernate (HQL) ในเมธอด readData()

แทนที่เนื้อหาของ App.java ด้วยเนื้อหาต่อไปนี้

src/main/java/codelab/App.java

package codelab;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

public class App {

  public final static DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");

  public static void main(String[] args) {
    // create a Hibernate sessionFactory and session
    StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();
    SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata()
        .buildSessionFactory();
    Session session = sessionFactory.openSession();

    clearData(session);

    writeData(session);

    readData(session);

    // close Hibernate session and sessionFactory
    session.close();
    sessionFactory.close();
  }

  private static void clearData(Session session) {
    session.beginTransaction();

    session.createQuery("delete from Album where 1=1").executeUpdate();
    session.createQuery("delete from Singer where 1=1").executeUpdate();

    session.getTransaction().commit();
  }

  private static void writeData(Session session) {
    session.beginTransaction();

    Singer singerMelissa = new Singer("Melissa", "Garcia", makeDate("1981-03-19"));
    Album albumGoGoGo = new Album(singerMelissa, "Go, Go, Go");
    session.save(singerMelissa);
    session.save(albumGoGoGo);

    session.save(new Singer("Russell", "Morales", makeDate("1978-12-02")));
    session.save(new Singer("Jacqueline", "Long", makeDate("1990-07-29")));
    session.save(new Singer("Dylan"<;, &qu>ot;Shaw", makeDate("1998-05-02")));

    sess>ion.getTransaction().commit();
  }

  private static void re<adDat>a(Session session) {
    ListSinger singers = session.createQuery("from Singer where birthDate = '1990-01-01' order by lastName")
        .list();
    ListAlbum albums = session.createQuery("from Album").list();

    System.out.println("Singers who were born in 1990 or later:");
    for (Singer singer : singers) {
      System.out.println(singer.getFirstName() + " " + singer.getLastName() + " born on "
          + DATE_FORMAT.format(singer.getBirthDate()));
    }

    System.out.println("Albums: ");
    for (Album album : albums) {
      System.out
          .println("\"" + album.getAlbumTitle() + "\" by " + album.getSinger().getFirstName() + &quot; "
              + album.getSinger().getLastName());
    }
  }

  private static Date makeDate(String dateString) {
    try {
      return DATE_FORMAT.parse(dateString);
    } catch (ParseException e) {
      e.printStackTrace();
      return null;
    }
  }
}

ตอนนี้มาคอมไพล์และเรียกใช้โค้ดกัน เราจะเพิ่มตัวเลือก -Dexec.cleanupDaemonThreads=false เพื่อระงับคำเตือนเกี่ยวกับการล้างข้อมูล Daemon Thread ที่ Maven จะพยายามทำ

mvn compile exec:java -Dexec.mainClass=codelab.App -Dexec.cleanupDaemonThreads=false

ในเอาต์พุต คุณควรเห็นข้อความต่อไปนี้

Singers who were born in 1990 or later:
Jacqueline Long born on 1990-07-29
Dylan Shaw born on 1998-05-02
Albums: 
"Go, Go, Go" by Melissa Garcia

ในตอนนี้ หากคุณไปที่ คอนโซล Cloud Spanner และดูข้อมูลสำหรับตาราง Singer และ Album ในฐานข้อมูล คุณจะเห็นข้อความต่อไปนี้

f18276ea54cc266f.png952d9450dd659e75.png

9. ล้างข้อมูล

มาลบอินสแตนซ์ Cloud Spanner ที่เราสร้างขึ้นในตอนต้นเพื่อให้แน่ใจว่าอินสแตนซ์จะไม่ใช้ทรัพยากรโดยไม่จำเป็น

gcloud spanner instances delete codelab-instance

10. ขอแสดงความยินดี

ขอแสดงความยินดี คุณสร้างแอปพลิเคชัน Java ที่ใช้ Hibernate เพื่อเก็บข้อมูลใน Cloud Spanner ได้สำเร็จแล้ว

  • คุณสร้างอินสแตนซ์ Cloud Spanner และฐานข้อมูลแล้ว
  • คุณกำหนดค่าแอปพลิเคชันให้ใช้ Hibernate แล้ว
  • คุณสร้างเอนทิตี 2 รายการ ได้แก่ ศิลปินและอัลบั้ม
  • คุณสร้างสคีมาฐานข้อมูลสำหรับแอปพลิเคชันโดยอัตโนมัติ
  • คุณบันทึกเอนทิตีลงใน Cloud Spanner และค้นหาเอนทิตีเหล่านั้นได้สำเร็จแล้ว

ตอนนี้คุณทราบขั้นตอนสำคัญที่ต้องใช้ในการเขียนแอปพลิเคชัน Hibernate ด้วย Cloud Spanner แล้ว

สิ่งต่อไปที่ควรทำ