MongoDB
 sql >> Teknologi Basis Data >  >> NoSQL >> MongoDB

Pengantar Morphia – Java ODM untuk MongoDB

1. Ikhtisar

Dalam tutorial ini, kita akan memahami bagaimana menggunakan Morphia, sebuah Object Document Mapper (ODM) untuk MongoDB di Java.

Dalam prosesnya, kami juga akan memahami apa itu ODM dan bagaimana memfasilitasi bekerja dengan MongoDB.

2. Apa itu ODM ?

Bagi mereka yang belum tahu di bidang ini, MongoDB adalah database berorientasi dokumen yang dibangun untuk didistribusikan secara alami . Database berorientasi dokumen, dalam istilah sederhana, mengelola dokumen, yang tidak lain adalah cara tanpa skema untuk mengatur data semi-terstruktur . Mereka berada di bawah payung database NoSQL yang lebih luas dan didefinisikan secara longgar, dinamai berdasarkan keberangkatan mereka dari organisasi tradisional database SQL.

MongoDB menyediakan driver untuk hampir semua bahasa pemrograman populer seperti Java . Driver ini menawarkan lapisan abstraksi untuk bekerja dengan MongoDB sehingga kami tidak bekerja dengan Wire Protocol secara langsung. Anggap ini sebagai Oracle yang menyediakan implementasi driver JDBC untuk database relasional mereka.

Namun, jika kita mengingat hari-hari kita bekerja dengan JDBC secara langsung, kita dapat menghargai betapa berantakannya hal itu — terutama dalam paradigma berorientasi objek. Untungnya, kami memiliki kerangka kerja Pemetaan Relasional Objek (ORM) seperti Hibernate untuk menyelamatkan kami. Tidak jauh berbeda dengan MongoDB.

Meskipun kami pasti dapat bekerja dengan driver tingkat rendah, ini membutuhkan lebih banyak boilerplate untuk menyelesaikan tugas. Di sini, kami memiliki konsep yang mirip dengan ORM yang disebut Object Document Mapper (ODM) . Morphia benar-benar mengisi ruang itu untuk bahasa pemrograman Java dan bekerja di atas driver Java untuk MongoDB.

3. Menyiapkan Dependensi

Kami telah melihat cukup banyak teori untuk memasukkan kami ke dalam beberapa kode. Sebagai contoh, kami akan membuat model perpustakaan buku dan melihat bagaimana kami dapat mengelolanya di MongoDB menggunakan Morphia.

Namun sebelum kita mulai, kita perlu menyiapkan beberapa dependensi.

3.1. MongoDB

Kita perlu memiliki instance MongoDB yang sedang berjalan untuk digunakan. Ada beberapa cara untuk mendapatkannya, dan yang paling sederhana adalah mengunduh dan menginstal edisi komunitas di komputer lokal kami.

Kita harus membiarkan semua konfigurasi default apa adanya, termasuk port tempat MongoDB berjalan.

3.2. Morfia

Kami dapat mengunduh JAR pra-bangun untuk Morphia dari Maven Central dan menggunakannya dalam proyek Java kami.

Namun, cara paling sederhana adalah dengan menggunakan alat manajemen ketergantungan seperti Maven:

<dependency>
    <groupId>dev.morphia.morphia</groupId>
    <artifactId>core</artifactId>
    <version>1.5.3</version>
</dependency>

4. Bagaimana Menghubungkan Menggunakan Morphia?

Sekarang kita telah menginstal dan menjalankan MongoDB dan telah menyiapkan Morphia di proyek Java kita, kita siap untuk terhubung ke MongoDB menggunakan Morphia.

Mari kita lihat bagaimana kita bisa mencapainya:

Morphia morphia = new Morphia();
morphia.mapPackage("com.baeldung.morphia");
Datastore datastore = morphia.createDatastore(new MongoClient(), "library");
datastore.ensureIndexes();

Itu cukup banyak! Mari kita memahami ini lebih baik. Kami membutuhkan dua hal agar operasi pemetaan kami berfungsi:

  1. Pemeta:Ini bertanggung jawab untuk memetakan POJO Java kami ke Koleksi MongoDB . Dalam cuplikan kode kami di atas, Morphia adalah kelas yang bertanggung jawab untuk itu. Perhatikan bagaimana kami mengonfigurasi paket di mana ia seharusnya mencari POJO kami.
  2. Koneksi:Ini adalah koneksi ke database MongoDB di mana mapper dapat menjalankan operasi yang berbeda. Kelas Datastore mengambil sebagai parameter sebuah instance dari MongoClient (dari driver Java MongoDB) dan nama database MongoDB, mengembalikan koneksi aktif untuk bekerja dengan .

Jadi, kita sudah siap untuk menggunakan Datastore ini dan bekerja dengan entitas kami.

5. Bagaimana Bekerja dengan Entitas?

Sebelum kami dapat menggunakan Datastore kami yang baru dicetak , kita perlu mendefinisikan beberapa entitas domain untuk digunakan.

5.1. Entitas Sederhana

Mari kita mulai dengan mendefinisikan Buku sederhana entitas dengan beberapa atribut:

@Entity("Books")
public class Book {
    @Id
    private String isbn;
    private String title;
    private String author;
    @Property("price")
    private double cost;
    // constructors, getters, setters and hashCode, equals, toString implementations
}

Ada beberapa hal menarik yang perlu diperhatikan di sini:

  • Perhatikan anotasi @Entitas yang memenuhi syarat POJO ini untuk pemetaan ODM oleh Morphia
  • Morphia, secara default, memetakan entitas ke koleksi di MongoDB dengan nama kelasnya, tetapi kita dapat secara eksplisit menimpanya (seperti yang telah kita lakukan untuk entitas Buku di sini)
  • Morphia, secara default, memetakan variabel dalam entitas ke kunci dalam koleksi MongoDB dengan nama variabel, tetapi sekali lagi kita dapat menimpanya (seperti yang telah kita lakukan untuk variabel biaya di sini)
  • Terakhir, kita perlu menandai variabel dalam entitas untuk bertindak sebagai kunci utama dengan anotasi @Id (seperti kami menggunakan ISBN untuk buku kami di sini)

5.2. Entitas dengan Hubungan

Namun, di dunia nyata, entitas tidak sesederhana kelihatannya dan memiliki hubungan yang kompleks satu sama lain. Misalnya, entitas sederhana kami Buku dapat memiliki Penerbit dan dapat mereferensikan buku-buku pendamping lainnya. Bagaimana kita memodelkannya?

MongoDB menawarkan dua mekanisme untuk membangun hubungan — Referensi dan Penyematan . Seperti namanya, dengan referensi, MongoDB menyimpan data terkait sebagai dokumen terpisah dalam koleksi yang sama atau berbeda dan hanya mereferensikannya menggunakan id-nya.

Sebaliknya, dengan penyematan, MongoDB menyimpan atau lebih tepatnya menyematkan relasi di dalam dokumen induk itu sendiri.

Mari kita lihat bagaimana kita bisa menggunakannya. Mari kita mulai dengan menyematkan Penerbit di Buku kami :

@Embedded
private Publisher publisher;

Cukup sederhana. Sekarang mari kita lanjutkan dan tambahkan referensi ke buku lain:

@Reference
private List<Book> companionBooks;

Itu saja — Morphia menyediakan anotasi yang nyaman untuk memodelkan hubungan yang didukung oleh MongoDB. Pilihan mereferensi vs menyematkan, bagaimanapun, harus diambil dari kompleksitas model data, redundansi, dan konsistensi di antara pertimbangan lainnya.

Latihan ini mirip dengan normalisasi dalam database relasional.

Sekarang, kami siap untuk melakukan beberapa operasi pada Buku menggunakan Datastore .

6. Beberapa Operasi Dasar

Mari kita lihat bagaimana bekerja dengan beberapa operasi dasar menggunakan Morphia.

6.1. Simpan

Mari kita mulai dengan operasi paling sederhana, membuat instance Book di perpustakaan database MongoDB kami :

Publisher publisher = new Publisher(new ObjectId(), "Awsome Publisher");

Book book = new Book("9781565927186", "Learning Java", "Tom Kirkman", 3.95, publisher);
Book companionBook = new Book("9789332575103", "Java Performance Companion", 
  "Tom Kirkman", 1.95, publisher);

book.addCompanionBooks(companionBook);

datastore.save(companionBook);
datastore.save(book);

Ini cukup untuk memungkinkan Morphia membuat koleksi di database MongoDB kami, jika tidak ada, dan melakukan operasi upsert.

6.2. Kueri

Mari kita lihat apakah kita dapat menanyakan buku yang baru saja kita buat di MongoDB:

List<Book> books = datastore.createQuery(Book.class)
  .field("title")
  .contains("Learning Java")
  .find()
  .toList();

assertEquals(1, books.size());

assertEquals(book, books.get(0));

Membuat kueri dokumen di Morphia dimulai dengan membuat kueri menggunakan Datastore dan kemudian menambahkan filter secara deklaratif, untuk menyenangkan mereka yang menyukai pemrograman fungsional!

Morphia mendukung konstruksi kueri yang jauh lebih kompleks dengan filter dan operator. Selain itu, Morphia memungkinkan untuk membatasi, melewatkan, dan mengurutkan hasil dalam kueri.

Terlebih lagi, Morphia memungkinkan kita menggunakan kueri mentah yang ditulis dengan driver Java untuk MongoDB untuk kontrol lebih, jika diperlukan.

6.3. Perbarui

Meskipun operasi penyimpanan dapat menangani pembaruan jika kunci utama cocok, Morphia menyediakan cara untuk memperbarui dokumen secara selektif:

Query<Book> query = datastore.createQuery(Book.class)
  .field("title")
  .contains("Learning Java");

UpdateOperations<Book> updates = datastore.createUpdateOperations(Book.class)
  .inc("price", 1);

datastore.update(query, updates);

List<Book> books = datastore.createQuery(Book.class)
  .field("title")
  .contains("Learning Java")
  .find()
  .toList();

assertEquals(4.95, books.get(0).getCost());

Di sini, kami membuat kueri dan operasi pembaruan untuk menaikkan satu harga semua buku yang dikembalikan oleh kueri.

6.4. Hapus

Akhirnya, apa yang telah dibuat harus dihapus! Sekali lagi, dengan Morphia, ini cukup intuitif:

Query<Book> query = datastore.createQuery(Book.class)
  .field("title")
  .contains("Learning Java");

datastore.delete(query);

List<Book> books = datastore.createQuery(Book.class)
  .field("title")
  .contains("Learning Java")
  .find()
  .toList();

assertEquals(0, books.size());

Kami membuat kueri cukup mirip seperti sebelumnya dan menjalankan operasi penghapusan di Datastore .

7. Penggunaan Lanjutan

MongoDB memiliki beberapa operasi lanjutan seperti Agregasi, Pengindeksan, dan banyak lainnya . Meskipun tidak mungkin untuk melakukan semua itu menggunakan Morphia, tentu saja mungkin untuk mencapai sebagian dari itu. Untuk yang lain, sayangnya, kita harus kembali ke driver Java untuk MongoDB.

Mari kita fokus pada beberapa operasi lanjutan yang dapat kita lakukan melalui Morphia.

7.1. Agregasi

Agregasi di MongoDB memungkinkan kita untuk mendefinisikan serangkaian operasi dalam pipa yang dapat beroperasi pada sekumpulan dokumen dan menghasilkan output gabungan .

Morphia memiliki API untuk mendukung alur agregasi semacam itu.

Mari kita asumsikan kita ingin menggabungkan data perpustakaan kita sedemikian rupa sehingga kita memiliki semua buku yang dikelompokkan berdasarkan penulisnya:

Iterator<Author> iterator = datastore.createAggregation(Book.class)
  .group("author", grouping("books", push("title")))
  .out(Author.class);

Jadi, bagaimana cara kerjanya? Kita mulai dengan membuat pipeline agregasi menggunakan Datastore old lama yang sama . Kami harus menyediakan entitas tempat kami ingin melakukan operasi agregasi, misalnya, Buku di sini.

Selanjutnya, kami ingin mengelompokkan dokumen berdasarkan "penulis" dan menggabungkan "judul" mereka di bawah kunci yang disebut "buku". Akhirnya, kami bekerja dengan ODM di sini. Jadi, kita harus mendefinisikan entitas untuk mengumpulkan data agregat kita — dalam kasus kita, itu adalah Penulis .

Tentu saja, kita harus mendefinisikan entitas yang disebut Penulis dengan variabel yang disebut buku:

@Entity
public class Author {
    @Id
    private String name;
    private List<String> books;
    // other necessary getters and setters
}

Ini, tentu saja, hanya menggores permukaan konstruksi yang sangat kuat yang disediakan oleh MongoDB dan dapat dieksplorasi lebih lanjut untuk detailnya.

7.2. Proyeksi

Proyeksi di MongoDB memungkinkan kita untuk hanya memilih bidang yang ingin kita ambil dari dokumen dalam kueri kita . Jika struktur dokumen rumit dan berat, ini bisa sangat berguna ketika kita hanya membutuhkan beberapa bidang.

Misalkan kita hanya perlu mengambil buku dengan judulnya dalam kueri kita:

List<Book> books = datastore.createQuery(Book.class)
  .field("title")
  .contains("Learning Java")
  .project("title", true)
  .find()
  .toList();
 
assertEquals("Learning Java", books.get(0).getTitle());
assertNull(books.get(0).getAuthor());

Di sini, seperti yang bisa kita lihat, kita hanya mendapatkan kembali judul di hasil kita dan bukan penulis dan bidang lainnya. Namun, kita harus berhati-hati dalam menggunakan keluaran yang diproyeksikan dalam menyimpan kembali ke MongoDB. Hal ini dapat mengakibatkan hilangnya data!

7.3. Pengindeksan

Indeks memainkan peran yang sangat penting dalam pengoptimalan kueri dengan database — relasional maupun non-relasional.

MongoDB mendefinisikan indeks pada tingkat koleksi dengan indeks unik yang dibuat pada kunci utama secara default . Selain itu, MongoDB memungkinkan indeks dibuat di bidang atau sub-bidang apa pun di dalam dokumen. Kita harus memilih untuk membuat indeks pada kunci tergantung pada kueri yang ingin kita buat.

Misalnya, dalam contoh kita, kita mungkin ingin membuat indeks pada bidang “judul” dari Buku seperti yang sering kita tanyakan padanya:

@Indexes({
  @Index(
    fields = @Field("title"),
    options = @IndexOptions(name = "book_title")
  )
})
public class Book {
    // ...
    @Property
    private String title;
    // ...
}

Tentu saja, kami dapat memberikan opsi pengindeksan tambahan untuk menyesuaikan nuansa indeks yang dibuat. Perhatikan bahwa bidang harus dianotasi dengan @Properti untuk digunakan dalam indeks.

Selain itu, selain indeks tingkat kelas, Morphia juga memiliki anotasi untuk menentukan indeks tingkat bidang.

7.4. Validasi Skema

Kami memiliki opsi untuk menyediakan aturan validasi data untuk koleksi yang dapat digunakan MongoDB saat melakukan operasi pembaruan atau penyisipan . Morphia mendukung ini melalui API mereka.

Katakanlah kita tidak ingin memasukkan buku tanpa harga yang valid. Kami dapat memanfaatkan validasi skema untuk mencapai ini:

@Validation("{ price : { $gt : 0 } }")
public class Book {
    // ...
    @Property("price")
    private double cost;
    // ...
}

Ada banyak set validasi yang disediakan oleh MongoDB yang dapat digunakan di sini.

8. ODM MongoDB Alternatif

Morphia bukan satu-satunya MongoDB ODM yang tersedia untuk Java. Ada beberapa lainnya yang dapat kami pertimbangkan untuk digunakan dalam aplikasi kami. Diskusi tentang perbandingan dengan Morphia tidak mungkin dilakukan di sini, tetapi selalu berguna untuk mengetahui opsi kami:

  • Data Musim Semi:Menyediakan model pemrograman berbasis Musim Semi untuk bekerja dengan MongoDB
  • MongoJack:Menyediakan pemetaan langsung dari JSON ke objek MongoDB

Ini bukan daftar lengkap ODM MongoDB untuk Java, tetapi ada beberapa alternatif menarik yang tersedia!


No
  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Upsert Cepat atau Massal di pymongo

  2. Apakah ada cara untuk mengimplementasikan pagination di webflux pegas dan data pegas reaktif

  3. Mongodb Gabung di bidang _id dari String ke ObjectId

  4. Mongoose - Simpan array string

  5. MongoDB $tahun