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

1. ภาพรวม

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

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

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

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

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

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

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

การตั้งค่าสภาพแวดล้อมตามเวลาที่สะดวก

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

k6ai2NRmxIjV5iMFlVgA_ZyAWE4fhRrkrZZ5mZuCas81YLgk0iwIyvgoDet4s2lMYGC5K3xLSOjIbmC9kjiezvQuxuhdYRolbv1rft1lOmA_P2U3OYcaAzN9JgP-Ncm18i5qgf9LzA

UtcCMcSYtCOrEWuILx3XBwb3GILPqXDd6cJiQQxmylg8GNftqlnE7u8aJLhlr1ZLRkpncKdj8ERnqcH71wab2HlfUnO9CgXKd0-CAQC2t3CH0kuQRxdtP0ws43t5-O2d4d0WXDUfaw

KoK3nfWQ73s_x4QI69xqzqdDR4tUuNmrv4FC9Yq8vtK5IVm49h_8h6x9X281hAcJcOFDtX7g2BXPvP5O7SOR2V4UI6W8gN6cTJCVAdtWHRrS89zH-qWE0IQdjFpOs_8T-s4vQCXA6w

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

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

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

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

  1. คลิกเปิดใช้งาน Cloud Shell R47NpBm6yyzso5vnxnRBikeDAXxl3LsM6เคล็ดลับ3rJxnKuS2EZdCI0h-eIOGm9aECq8JXbMFlJkd68uTutXU8gGmQUVa5iI1OdZczXP2tzqWZwZczDR7P2tzqZ_mj0p จาก Cloud Console

STsYbcAtkIQyN6nL9BJhld3Fv5KxedYynpUVcRWwvIR-sYMMc4kfK-unIYgtsD4P6T0P8z-A12388tPmAh-Trsx80qobaW4KQXHJ7qJI6rwm762LrxurYbxwiDG-v_HiUYsWnXMciw

หากคุณไม่เคยเริ่มต้นใช้งาน 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 ในการสร้างแอปพลิเคชันคอนโซล 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 ที่ใช้ไฮเบอร์เนตเพื่อพูดคุยกับ Cloud Spanner สำหรับการดำเนินการดังกล่าว เราต้องใช้ Cloud Spanner Dialect สำหรับ Hibernate, ไดรเวอร์ JDBC ของ Cloud Spanner และแกนหลักของไฮเบอร์เนต ดังนั้น เราจะเพิ่มการอ้างอิงต่อไปนี้ไปยังบล็อก <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

ต่อไป เราจะสร้างไฟล์การกำหนดค่า Hibernet 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>

นอกจากนี้ Hibernet ยังจำเป็นต้องทราบวิธีเชื่อมต่อกับอินสแตนซ์ Cloud Spanner และภาษาถิ่นที่จะใช้ ดังนั้น เราจะบอกให้ใช้ 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 (POJO) เก่าธรรมดา 2 รายการที่จะแมปกับตารางใน 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 ของไฮเบอร์เนต แล้วใช้คำสั่งนี้เพื่อลบแถวตารางทั้งหมดในเมธอด clearData() ก่อน แล้วบันทึกเอนทิตีบางรายการในเมธอด writeData() และเรียกใช้การค้นหาบางรายการโดยใช้ภาษาคำสั่งไฮเบอร์เนต (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", "Shaw", makeDate("1998-05-02")));

    session.getTransaction().commit();
  }

  private static void readData(Session session) {
    List<Singer> singers = session.createQuery("from Singer where birthDate >= '1990-01-01' order by lastName")
        .list();
    List<Album> 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() + " "
              + 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 ที่ 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 และดูข้อมูลสำหรับตารางนักร้องและอัลบั้มในฐานข้อมูล คุณจะเห็นข้อมูลดังนี้

f18276ea54cc266f.png

952d9450dd659e75.png

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

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

gcloud spanner instances delete codelab-instance

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

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

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

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

สิ่งที่ต้องทำต่อไป