Jika Anda telah bekerja dengan Spring Data JPA untuk waktu yang lama - Anda mungkin mengenal metode kueri turunan
@Repository public interface BookRepository extends MongoRepository { List findByAuthor(String name); }Mereka adalah cara yang bagus dan cepat untuk melepaskan beban menulis kueri ke Spring Data JPA hanya dengan mendefinisikan nama metode
Dalam skenario hipotetis ini - kami telah mendefinisikan logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG 6 untuk kelas logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG 7, yang memiliki atribut bernama logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG 8 bertipe logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG 9
Pengingat. logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG 6 hanyalah public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 1 khusus yang cocok untuk Mongo, yang pada gilirannya merupakan public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 2 khusus
Alih-alih menerapkan metode ini dalam implementasi layanan public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 3 - Spring Data JPA menghasilkan kueri secara otomatis dengan nama metode. Ini akan menghasilkan kueri yang mengembalikan daftar semua catatan logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG 7, dengan logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG 8 yang cocok
Setelah metode dipanggil dengan beberapa input, permintaan berikut dibuat
find using query: { "author" : "Max Tegmark"} fields: Document{{}} for class: class com.example.demo.Book in collection: booksCatatan. Untuk melihat output ini, Anda harus menyetel level debugging dari public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 6 ke public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 7
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG _Ini adalah fitur yang sangat fleksibel dan kuat dari Spring Data JPA dan memungkinkan Anda untuk mem-bootstrap kueri tanpa menulis kueri itu sendiri, atau bahkan menerapkan logika penanganan apa pun di back-end
Namun, mereka menjadi sangat sulit untuk dibuat ketika kueri kompleks diperlukan
public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } _Dan ini hanya untuk dua parameter. Apa yang terjadi jika Anda ingin membuat kueri untuk 5 parameter?
Juga, berapa banyak variasi metode yang akan Anda buat?
Ini adalah titik ketika Anda kemungkinan besar ingin memilih untuk menulis kueri Anda sendiri. Ini dapat dilakukan melalui anotasi public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } _8
Anotasi public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 8 diterapkan pada tingkat metode di antarmuka logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG 6, dan berkaitan dengan satu metode. Bahasa yang digunakan di dalam anotasi bergantung pada back-end Anda. Secara alami, untuk back-end Mongo, Anda akan menulis kueri Mongo asli, meskipun, public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 8 juga mendukung basis data relasional, dan menerima kueri asli untuknya, atau JPQL netral (Java Persistence Query Language) yang diterjemahkan secara otomatis ke kueri asli dari
Saat metode beranotasi dipanggil - kueri dari dalam public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 8 anotasi menyala dan mengembalikan hasilnya
Catatan. Panduan ini akan mencakup Spring Data JPA digabungkan dengan database Mongo, dan akan menggunakan kueri yang berlaku untuk MongoDB
Jika Anda ingin membaca lebih lanjut tentang menulis kueri relasional/SQL, baca Spring Data JPA kami - Panduan untuk Anotasi @Query
Model Domain dan Repositori
Mari segera tentukan model logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG _7 yang akan kita gunakan sebagai public interface BookRepository extends MongoRepository { } 4 untuk repositori kita. Untuk memamerkan berbagai operasi dengan benar, seperti menggunakan operator public interface BookRepository extends MongoRepository { } 5 dan public interface BookRepository extends MongoRepository { } 6 Mongo, - kita akan memiliki beberapa properti berbeda
MongoDB berurusan dengan ID tipe logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG 9 atau public interface BookRepository extends MongoRepository { } 8. Terserah Anda untuk memilih mana yang akan Anda gunakan - dan public interface BookRepository extends MongoRepository { } 8 dapat dengan mudah diubah menjadi Strings dan sebaliknya sehingga tidak membuat banyak perbedaan
Bagaimanapun, mari kita tentukan public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 3 sederhana untuk model ini
public interface BookRepository extends MongoRepository { }Saat ini kosong, tetapi berfungsi dengan baik untuk operasi CRUD, mengingat fakta bahwa logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG 6 adalah turunan dari antarmuka public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 2. Selain itu, paging dan penyortiran didukung di luar kotak
Di bagian yang akan datang, kita akan melihat anotasi public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 8 itu sendiri, serta struktur kueri MongoDB, cara merujuk parameter metode serta pengurutan dan halaman
Memahami Anotasi @Query
Anotasi public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 8 cukup sederhana dan lugas
@Query("mongo query") public List findBy(String param1, String param2);Setelah metode @Query("mongo query") public List findBy(String param1, String param2); _5 dipanggil, hasilnya dikembalikan. Perlu diingat bahwa selama waktu kompilasi, Spring Boot tidak mengetahui jenis kueri apa yang akan dikembalikan sebelumnya. Misalnya, jika mengembalikan beberapa hasil, dan Anda hanya memiliki satu nilai pengembalian yang diharapkan - pengecualian akan dilemparkan selama runtime
Terserah Anda untuk memastikan bahwa respons kueri cocok dengan tipe pengembalian metode
Anda dapat memiliki kueri tetap atau dinamis di sini. Misalnya, Anda dapat menyederhanakan nama metode dari sebelumnya dan mendelegasikan parameter yang berantakan ke anotasi public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 8
@Query("query with param1, param2, param3") List findAllActive(); @Query("query with param1, param2, param3") List findBy(param1, param2, param3);Pada contoh pertama, kami memiliki kumpulan parameter tetap, seperti selalu mencari buku aktif meskipun klien tidak menentukannya. Ini merupakan keunggulan dibandingkan metode kueri turunan karena nama metode bersih. Sebagai alternatif, Anda dapat memberikan parameter ke metode yang kemudian dapat disuntikkan ke dalam anotasi public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 8 itu sendiri
@Query("{'active':true}") List findAll(); @Query("{'author' : ?0, 'category' : ?1}") List findPositionalParameters(String author, String category); @Query("{'author' : :#{#author}, 'category' : :#{#category}}") List findNamedParameters(@Param("author") String author, @Param("category") String category);Bagi mereka yang mungkin tidak sepenuhnya mengenal struktur kueri MongoDB, mari kita pelajari terlebih dahulu sebelum menggali parameter metode ekstraksi dan menggunakannya dalam kueri
Struktur Kueri MongoDB
MongoDB memiliki struktur kueri yang cukup mudah, meskipun berbeda dari struktur SQL. Jika Anda belum pernah menggunakan MongoDB sebelumnya dan jika Anda terbiasa dengan basis data relasional, sebaiknya segarkan memori Anda pada struktur ini
Semua kueri Mongodb terjadi di antara tanda kurung kurawal
{query}Kondisi kesetaraan standar mengikuti pola sederhana
{ : , : , .. }Misalnya, kami dapat meminta buku kami sebagai
Kueri ini memeriksa semua logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG _7 dokumen dalam koleksi, yang sesuai dengan logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG 8 dan @Query("query with param1, param2, param3") List findAllActive(); @Query("query with param1, param2, param3") List findBy(param1, param2, param3); 0Number`. Anda juga dapat memasukkan operator ke dalam campuran di sini
find using query: { "author" : "Max Tegmark"} fields: Document{{}} for class: class com.example.demo.Book in collection: books _1Kueri ini memeriksa apakah logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG _8 adalah salah satu dari nilai yang diberikan. Beberapa operator yang didukung adalah @Query("query with param1, param2, param3") List findAllActive(); @Query("query with param1, param2, param3") List findBy(param1, param2, param3); 2, @Query("query with param1, param2, param3") List findAllActive(); @Query("query with param1, param2, param3") List findBy(param1, param2, param3); 3, @Query("query with param1, param2, param3") List findAllActive(); @Query("query with param1, param2, param3") List findBy(param1, param2, param3); 4, @Query("query with param1, param2, param3") List findAllActive(); @Query("query with param1, param2, param3") List findBy(param1, param2, param3); 5, @Query("query with param1, param2, param3") List findAllActive(); @Query("query with param1, param2, param3") List findBy(param1, param2, param3); 6, @Query("query with param1, param2, param3") List findAllActive(); @Query("query with param1, param2, param3") List findBy(param1, param2, param3); 7, @Query("query with param1, param2, param3") List findAllActive(); @Query("query with param1, param2, param3") List findBy(param1, param2, param3); 8, @Query("query with param1, param2, param3") List findAllActive(); @Query("query with param1, param2, param3") List findBy(param1, param2, param3); 9 dan @Query("{'active':true}") List findAll(); @Query("{'author' : ?0, 'category' : ?1}") List findPositionalParameters(String author, String category); @Query("{'author' : :#{#author}, 'category' : :#{#category}}") List findNamedParameters(@Param("author") String author, @Param("category") String category); 0, meskipun ada beberapa yang perlu diketahui. Misalnya, inilah kueri yang mencari semua dokumen oleh salah satu dari dua penulis, dengan jumlah halaman antara 400 dan 500, tidak dirilis pada 2018 dan 2019
find using query: { "author" : "Max Tegmark"} fields: Document{{}} for class: class com.example.demo.Book in collection: books _2Lihat panduan praktis dan praktis kami untuk mempelajari Git, dengan praktik terbaik, standar yang diterima industri, dan menyertakan lembar contekan. Hentikan perintah Googling Git dan benar-benar pelajari itu
Ini adalah sebagian besar pengetahuan kueri yang Anda perlukan untuk banyak kueri, tetapi jangan lewatkan untuk benar-benar mengenal MongoDB sebelum serius bekerja dengannya. Selain itu, Anda mungkin juga ingin bekerja dengan agregasi
Jika Anda ingin membaca lebih lanjut tentang agregasi dengan MongoDB - baca Spring Data MongoDB kami - Panduan untuk Anotasi @Aggregation
Mereferensikan Parameter Metode Bernama dan Posisi
Dengan pengetahuan MongoDB fungsional di bawah ikat pinggang kita - mari kita lihat bagaimana kita bisa mereferensikan parameter metode. Anda dapat mereferensikannya baik melalui namanya, dicampur dengan anotasi @Query("{'active':true}") List findAll(); @Query("{'author' : ?0, 'category' : ?1}") List findPositionalParameters(String author, String category); @Query("{'author' : :#{#author}, 'category' : :#{#category}}") List findNamedParameters(@Param("author") String author, @Param("category") String category); 1 dan ekspresi SpEL, yang lebih bertele-tele tetapi lebih fleksibel, atau, melalui argumen posisional, yang biasanya merupakan pendekatan yang lebih disukai karena kesederhanaannya
find using query: { "author" : "Max Tegmark"} fields: Document{{}} for class: class com.example.demo.Book in collection: books _3Pada pendekatan pertama, argumen posisi pertama, @Query("{'active':true}") List findAll(); @Query("{'author' : ?0, 'category' : ?1}") List findPositionalParameters(String author, String category); @Query("{'author' : :#{#author}, 'category' : :#{#category}}") List findNamedParameters(@Param("author") String author, @Param("category") String category); 2, sesuai dengan argumen pertama dalam metode, dan nilai argumen akan digunakan sebagai pengganti @Query("{'active':true}") List findAll(); @Query("{'author' : ?0, 'category' : ?1}") List findPositionalParameters(String author, String category); @Query("{'author' : :#{#author}, 'category' : :#{#category}}") List findNamedParameters(@Param("author") String author, @Param("category") String category); 2. Ini berarti bahwa Anda harus melacak posisi dan tidak mencampuradukkannya, jika tidak, MongoDB akan gagal secara diam-diam dan tidak akan mengembalikan hasilnya, mengingat fleksibilitas skema, karena Anda mungkin juga memiliki properti itu
Tip. Jika Anda telah mengaktifkan public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } _7 sebagai tingkat pencatatan Anda - Anda akan dapat melihat kueri yang dikirim ke Mongo di log. Anda dapat menyalin-tempel kueri itu ke MongoDB Atlas untuk memeriksa apakah kueri mengembalikan hasil yang benar di sana, dan memverifikasi apakah Anda secara tidak sengaja telah mengacaukan posisinya. Kemungkinannya adalah - kueri Anda baik-baik saja, tetapi Anda baru saja mencampuradukkan posisinya, sehingga hasilnya kosong
Dalam pendekatan kedua, kami menggunakan ekspresi SpEL untuk mencocokkan parameter yang disediakan dengan parameter public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 8. Anda tidak perlu mendefinisikannya dalam urutan tertentu karena mereka akan dicocokkan dengan nama - bukan posisi. Padahal, masih masuk akal untuk menjaga posisi seragam untuk keterbacaan API
Mari kita tentukan titik akhir sederhana di pengontrol REST untuk menguji metode ini
find using query: { "author" : "Max Tegmark"} fields: Document{{}} for class: class com.example.demo.Book in collection: books _4Setelah disiapkan, mari kirim permintaan @Query("{'active':true}") List findAll(); @Query("{'author' : ?0, 'category' : ?1}") List findPositionalParameters(String author, String category); @Query("{'author' : :#{#author}, 'category' : :#{#category}}") List findNamedParameters(@Param("author") String author, @Param("category") String category); 6 (atau arahkan ke URL ini melalui browser)
find using query: { "author" : "Max Tegmark"} fields: Document{{}} for class: class com.example.demo.Book in collection: books _5Catatan. Untuk jawaban yang bagus, ingatlah untuk mengubah @Query("{'active':true}") List findAll(); @Query("{'author' : ?0, 'category' : ?1}") List findPositionalParameters(String author, String category); @Query("{'author' : :#{#author}, 'category' : :#{#category}}") List findNamedParameters(@Param("author") String author, @Param("category") String category); 7 Jackson menjadi @Query("{'active':true}") List findAll(); @Query("{'author' : ?0, 'category' : ?1}") List findPositionalParameters(String author, String category); @Query("{'author' : :#{#author}, 'category' : :#{#category}}") List findNamedParameters(@Param("author") String author, @Param("category") String category); 8 di @Query("{'active':true}") List findAll(); @Query("{'author' : ?0, 'category' : ?1}") List findPositionalParameters(String author, String category); @Query("{'author' : :#{#author}, 'category' : :#{#category}}") List findNamedParameters(@Param("author") String author, @Param("category") String category); 9 Anda
find using query: { "author" : "Max Tegmark"} fields: Document{{}} for class: class com.example.demo.Book in collection: books _6Hasil Paging dengan Halaman dan Pageable
Penyortiran dan paging didukung di luar kotak, karena logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG 6 memperluas public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 1. Seperti biasa, prosesnya adalah mengembalikan tipe {query} _2, dan menyediakan {query} 3 ke metode itu sendiri
Saat memanggil metode, Anda perlu menyediakan objek {query} 3 yang valid, yang dapat dibuat dengan membuat permintaan halaman
Di sini, kami membuat {query} _5 untuk halaman pertama (pengindeksan berbasis 0) dengan ukuran {query} 6 dokumen. Jika ada 10 dokumen pas di database, 5 halaman akan dikembalikan, mulai dari {query} 7. Anda harus membuat
Mari cetak seluruh objek {query} _2 yang kembali, di mana {query} 9 berisi hasil kueri, dan beberapa properti lainnya juga ada terkait dengan halaman. Di sinilah Anda dapat melihat bagaimana hasilnya diatur dalam halaman - i. e. penyortiran, ukuran halaman, nomor halaman, dll
find using query: { "author" : "Max Tegmark"} fields: Document{{}} for class: class com.example.demo.Book in collection: books _8Jika Anda hanya ingin menampilkan hasilnya, Anda dapat mengakses { : , : , .. } 0 data dan { : , : , .. } 1 ke daftar
find using query: { "author" : "Max Tegmark"} fields: Document{{}} for class: class com.example.demo.Book in collection: books _9Untuk memperluas fungsi ini dengan penyortiran, yang harus Anda lakukan adalah menyediakan objek { : , : , .. } 2 ke {query} 5, yang menyatakan properti mana yang ingin Anda urutkan dan urutannya
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG _0Di sini, kami telah mengurutkan hasil berdasarkan nama menaik dan nomor halaman menaik. Saat menyortir melalui beberapa properti, Anda dapat merangkai sejumlah properti melalui { : , : , .. } 4 dan memasok { : , : , .. } 5 lainnya
Metode { : , : , .. } _6 adalah metode default yang ada di antarmuka logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG 6, dan menerima instance { : , : , .. } 2 dan {query} 3, dan dapat dijalankan tanpa mereka juga. Di sini, kami memanfaatkannya untuk melakukan kueri menggunakan {query} 3 yang baru
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG _1Properti pertama diutamakan di sini. Meskipun buku kedua memiliki halaman lebih sedikit dari yang pertama, dan kami telah mengurutkan berdasarkan nomor halaman menaik, pengurutan berdasarkan nama menghasilkan urutan ini. Jika pesanan berdasarkan nama tidak jelas, properti kedua akan dipotong
Query dengan Operator
Semua yang dikatakan, mari buat ulang kueri dari awal artikel
find using query: { "author" : "Max Tegmark"} fields: Document{{}} for class: class com.example.demo.Book in collection: books _2Ini semudah menyalin-menempel kueri ini ke dalam anotasi public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 8. Mengetahui kami memiliki tiga buku, dan yang satu panjangnya 652 halaman, dan salah satunya diterbitkan pada tahun 2019 - kami berharap hanya satu buku yang dikembalikan ke sini - "Alam Semesta Matematika Kita" oleh Max Tegmark
Mari kita uji apakah itu benar
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG _3Atau, untuk implementasi yang lebih bersih
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG _4Catatan. Saat menyediakan array data, seperti find using query: { "author" : "Max Tegmark"} fields: Document{{}} for class: class com.example.demo.Book in collection: books 02 dan find using query: { "author" : "Max Tegmark"} fields: Document{{}} for class: class com.example.demo.Book in collection: books 03 - tidak perlu mendefinisikan parameter sebagai array dalam kueri - find using query: { "author" : "Max Tegmark"} fields: Document{{}} for class: class com.example.demo.Book in collection: books 04. Ini akan membuat array di dalam array. Anotasi public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 8 akan secara otomatis mengonversi input Anda menjadi kueri yang tepat
Mari perbarui titik akhir dan berikan beberapa data
Dan ketika kami mengirim permintaan untuk itu
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG _5Seperti jarum jam
Kesimpulan
Dalam panduan ini, kami telah melihat anotasi public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 8 dalam konteks Spring Data MongoDB
Anotasi memungkinkan Anda menentukan kueri Anda sendiri, asli dan JPQL, untuk berbagai basis data, relasional dan non-relasional. Kami telah memilih untuk menggunakan kueri Mongo asli untuk berinteraksi dengan database non-relasional. Setelah mendefinisikan model dan repositori untuknya, kami menjelajahi struktur kueri yang digunakan oleh MongoDB, dan cara kerja anotasi public interface PropertyRepository extends MongoRepository { List findPropertiesByTransactionTypeAndPropertyType(@Param("transaction_type") TransactionType transactionType, @Param("property_type") PropertyType propertyType); } 8 secara umum. Ini diikuti dengan mereferensikan parameter metode bernama dan posisional, paging dan menyortir hasil kueri, serta cara menggunakan operator MongoDB untuk membuat kueri yang lebih kompleks