हाइबरनेट ORM के साथ क्लाउड स्पैनर

1. खास जानकारी

हाइबरनेट, Java प्रोजेक्ट के लिए वास्तविक ORM समाधान बन गया है. यह सभी बड़े रिलेशनल डेटाबेस के साथ काम करता है. साथ ही, यह Spring Data JPA जैसे ज़्यादा ताकतवर ORM टूल को चालू करता है. इसके अलावा, यहां हाइबरनेट के साथ काम करने वाले कई फ़्रेमवर्क भी मौजूद हैं, जैसे कि Spring बूट, माइक्रोप्रोफ़ाइल, और क्वार्कस.

Hibernate ORM के लिए Cloud Spanner डायलेक्ट की मदद से, Cloud Spanner के साथ हाइबरनेट का इस्तेमाल किया जा सकता है. आपको हाइबरनेट की मुहावरे वाली स्थिरता के साथ-साथ Cloud Spanner - स्केलेबिलिटी और रिलेशनल सिमेंटिक्स के फ़ायदे मिलते हैं. इससे आपको मौजूदा ऐप्लिकेशन को क्लाउड पर माइग्रेट करने या नए ऐप्लिकेशन लिखने में मदद मिल सकती है. इसके लिए, Hibernate पर आधारित टेक्नोलॉजी के ज़रिए डेवलपर की ज़्यादा प्रोडक्टिविटी का इस्तेमाल किया जा सकता है.

आपको इनके बारे में जानकारी मिलेगी

  • Cloud Spanner से कनेक्ट होने वाला आसान Hibernate ऐप्लिकेशन लिखने का तरीका
  • क्लाउड स्पैनर डेटाबेस बनाने का तरीका
  • हाइबरनेट ORM के लिए क्लाउड स्पैनर डायलेक्ट का इस्तेमाल कैसे करें
  • हाइबरनेट के साथ, 'बनाएं-रीड-अपडेट-मिटाएं (सीआरयूडी)' कार्रवाइयों को लागू करने का तरीका

आपको इन चीज़ों की ज़रूरत होगी

  • Google Cloud Platform प्रोजेक्ट
  • ब्राउज़र, जैसे कि Chrome या Firefox

2. सेटअप और ज़रूरी शर्तें

अपने हिसाब से एनवायरमेंट सेटअप करना

  1. Cloud Console में साइन इन करें और नया प्रोजेक्ट बनाएं या किसी मौजूदा प्रोजेक्ट का फिर से इस्तेमाल करें. (अगर आपके पास पहले से Gmail या G Suite खाता नहीं है, तो आपको एक खाता बनाना होगा.)

k6ai2NRmxIjV5iMFlVgA_ZyAWE4fhRrkrZZ5mZuCas81YLgk0iwIyvgoDet4s2lMYGC5K3xLSOjIbmC9kjiezvQuxuhdYRolbv1rft1lOmA_P2U3OYcaAzN9JgP-Ncm18i5qgf9LzA

UtcCMcSYtCOrEWuILx3XBwb3GILPqXDd6cJiQQxmylg8GNftqlanE7u8aJLhlr1ZLRkpncKdj8ERnqcH71wab2HlfUnO9CgXKd0-CQC2t3d3CH0kuQ

KoK3nfWQ73s_x4QI69xqzqdDR4tUuNmrv4FC9Yq8vtK5IVm49h_8h6x9X281hAcJcOFDtX7g2BXPvP5O7SOR2V4UI6W8gN6cTJCVAdtWHRrS89zH-qWE0IQdjFpOs_8T-s4vQCXA6w

प्रोजेक्ट आईडी याद रखें. यह Google Cloud के सभी प्रोजेक्ट के लिए एक खास नाम होता है (ऊपर दिया गया नाम पहले ही ले लिया गया है और यह आपके लिए काम नहीं करेगा!). बाद में, इस कोडलैब को इस कोडलैब में PROJECT_ID के तौर पर दिखाया जाएगा.

  1. इसके बाद, आपको Google Cloud के संसाधनों का इस्तेमाल करने के लिए, Cloud Console में बिलिंग की सुविधा चालू करनी होगी.

इस कोडलैब का इस्तेमाल करने पर, आपको ज़्यादा पैसे नहीं चुकाने होंगे. "साफ़ करना" सेक्शन में दिए गए निर्देशों का पालन करना न भूलें सेक्शन में, संसाधनों को बंद करने का तरीका बताया गया है. इससे इस ट्यूटोरियल के अलावा बिलिंग की सुविधा नहीं मिलेगी. Google Cloud के नए उपयोगकर्ता, 300USD डॉलर के मुफ़्त में आज़माने वाले प्रोग्राम में हिस्सा ले सकते हैं.

Cloud Shell चालू करें

  1. Cloud Console में, Cloud Shell चालू करें R47NpBm6yyzso5vnxnRBikeDAXxl3LsM6tip3rJxnKuS2EZdCI0h-eIOGm9aECq8JXbMFlJkd68uTutXU8gGmQUVa5iI1OdZczXP2tzq4OMtDR पर क्लिक करें.

STsYbcAtkIQyN6nL9BJhld3Fv5KxedYynpUVcRWwvIR-sYMMc4kfK-unIYgtsD4P6T0P8z-A12388tPmAh-Trsx80qobaW4KQXHJ7qJI6rwm762LrxurYbxwiDG-v_HiUYsWnXMciw

अगर आपने Cloud Shell का इस्तेमाल पहले कभी नहीं किया है, तो आपको इसके बारे में जानकारी देने वाली एक इंटरमीडिएट स्क्रीन (पेज के फ़ोल्ड के नीचे) दिखेगी. अगर ऐसा है, तो जारी रखें पर क्लिक करें (यह आपको फिर कभी नहीं दिखेगा). एक बार इस्तेमाल होने वाली स्क्रीन कुछ इस तरह दिखती है:

LnGMTn1ObgwWFtWpjSdzlA9TDvSbcY76GiLQLc_f7RP1QBK1Tl4H6kLCHzsi89Lkc-serOpqNH-F2XKmV5AnBqTbPon4HvCwSSrY_ERFHzeYmK1lnTfr-6x5eVoaHpRSrCUrolXUPQ

प्रावधान करने और Cloud Shell से कनेक्ट होने में कुछ ही समय लगेगा.

hfu9bVHmrWw01Hnrlf4MBNja6yvssDnZzN9oupcG12PU88Vvo30tTluX9IySwnu5_TG3U2UXAasX9eCwqwZtc6Yhwxri95zG82DLUcKxrFYaXnVd7OqVoU6zanoZa0PtvubjLLHxnA

इस वर्चुअल मशीन में ऐसे सभी डेवलपमेंट टूल मौजूद हैं जिनकी आपको ज़रूरत पड़ेगी. यह पांच जीबी की स्थायी होम डायरेक्ट्री उपलब्ध कराता है और Google Cloud में चलता है. इससे नेटवर्क की परफ़ॉर्मेंस और पुष्टि करने की प्रक्रिया को बेहतर बनाने में मदद मिलती है. अगर सभी नहीं, तो इस कोडलैब में आपका बहुत सारा काम बस किसी ब्राउज़र या आपके 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 के लॉन्च होने के बाद, अपने GCP प्रोजेक्ट के साथ इंटरैक्ट करने के लिए gcloud का इस्तेमाल किया जा सकता है.

सबसे पहले, Cloud Spanner API को चालू करें.

gcloud services enable spanner.googleapis.com

अब codelab-instance नाम का Cloud Spanner इंस्टेंस बनाते हैं.

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. बिना सुविधा वाला ऐप्लिकेशन बनाएं

हम एक आसान Java कंसोल ऐप्लिकेशन बनाने के लिए, Maven क्विकस्टार्ट आर्कटाइप का इस्तेमाल करेंगे.

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. डिपेंडेंसी जोड़ें

सोर्स कोड के बारे में जानने के लिए, Cloud Shell Editor खोलें और spanner-hibernate-codelab डायरेक्ट्री में ब्राउज़ करें.

b5cb37d043d4d2b0.png

अभी तक, हमारे पास सिर्फ़ एक बेसिक Java कंसोल ऐप्लिकेशन है जो "Hello World!" को प्रिंट करता है. हालांकि, हम सच में एक ऐसा Java ऐप्लिकेशन लिखना चाहते हैं जो Cloud Spanner से बात करने के लिए Hibernate का इस्तेमाल करता है. इसके लिए, हमें हाइबरनेट के लिए क्लाउड स्पैनर डायलेक्ट, क्लाउड स्पैनर JDBC ड्राइवर और हाइबरनेट कोर की ज़रूरत होगी. इसलिए, pom.xml फ़ाइल के अंदर <dependencies> ब्लॉक में इन डिपेंडेंसी को जोड़ते हैं.

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 इंस्टेंस से कैसे कनेक्ट किया जाए और किस बोली का इस्तेमाल किया जाए. इसलिए, हम इसे SQL सिंटैक्स के लिए SpannerDialect, स्पैनर 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 प्रॉपर्टी जोड़ी है, ताकि जब हम पहली बार ऐप्लिकेशन को चलाते हैं, तो हाइबरनेट, Cloud Spanner में दो टेबल बना सके.

आम तौर पर, आपको यह भी पक्का करना होगा कि पुष्टि करने वाले क्रेडेंशियल, GOOGLE_APPLICATION_CREDENTIALS एनवायरमेंट वैरिएबल में सेवा खाते की JSON फ़ाइल का इस्तेमाल करके या gcloud auth application-default login कमांड का इस्तेमाल करके कॉन्फ़िगर किए गए ऐप्लिकेशन के डिफ़ॉल्ट क्रेडेंशियल का इस्तेमाल करके सेट अप किए गए हैं. हालांकि, हम Cloud Shell में काम कर रहे हैं, इसलिए डिफ़ॉल्ट प्रोजेक्ट क्रेडेंशियल पहले से ही सेट अप होते हैं.

7. व्याख्या की गई इकाई की क्लास बनाना

अब हम कुछ कोड लिखने के लिए तैयार हैं.

हम दो सादे पुराने Java ऑब्जेक्ट (POJO) बनाएंगे, जो Cloud Spanner में टेबल से मैप करेंगे—Singer और Album. Album का Singer के साथ @ManyToOne का संबंध होगा. हम 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;
  }
}

ध्यान दें कि इस उदाहरण में, हम मुख्य कुंजी के लिए अपने-आप जनरेट हुए यूयूआईडी का इस्तेमाल कर रहे हैं. यह Cloud Spanner में एक पसंदीदा आईडी टाइप है, क्योंकि यह हॉटस्पॉट का इस्तेमाल नहीं करता. ऐसा इसलिए, क्योंकि सिस्टम डेटा को सर्वर के बीच मुख्य रेंज के हिसाब से बांटता है. एक ही तरह से बढ़ती पूर्णांक कुंजी भी काम करेगी, लेकिन हो सकता है कि इसकी परफ़ॉर्मेंस कम हो.

8. इकाइयां सेव करें और क्वेरी करें

जब सब कुछ कॉन्फ़िगर किया गया हो और इकाई ऑब्जेक्ट तय किए गए हों, तब हम डेटाबेस में लिखना और उससे क्वेरी करना शुरू कर सकते हैं. हम एक Hibernate Session खोलेंगे और इसका इस्तेमाल, पहले clearData() तरीके में टेबल की सभी पंक्तियां मिटाने के लिए करेंगे. साथ ही, कुछ इकाइयों को writeData() तरीके में सेव करेंगे, और readData()मेथड में Hibernate query language (HQL) का इस्तेमाल करके कुछ क्वेरी चलाएं.

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 विकल्प जोड़ेंगे, ताकि डेमन थ्रेड क्लीनअप की प्रोसेस के बारे में 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 में डेटा को बनाए रखने के लिए Hibernate का इस्तेमाल करता है.

  • आपने Cloud Spanner इंस्टेंस और डेटाबेस बनाया है
  • आपने ऐप्लिकेशन को Hibernate का इस्तेमाल करने के लिए कॉन्फ़िगर किया है
  • आपने दो इकाइयां बनाई हैं: कलाकार और एल्बम
  • आपने अपने ऐप्लिकेशन के लिए डेटाबेस स्कीमा अपने-आप जनरेट किया है
  • आपने Cloud Spanner में इकाइयों को सेव कर लिया है और उनसे क्वेरी की है

अब आपको Cloud Spanner के साथ Hibernate ऐप्लिकेशन लिखने के ज़रूरी चरणों के बारे में पता है.

आगे क्या होगा?