1. Přehled
V tomto tutoriálu pochopíme, jak používat Morphia, objektový mapovač dokumentů (ODM) pro MongoDB v Javě.
Během tohoto procesu také pochopíme, co je ODM a jak usnadňuje práci s MongoDB.
2. Co je ODM ?
Pro ty, kteří v této oblasti nezasvěcení, MongoDB je databáze orientovaná na dokumenty vytvořená tak, aby byla přirozeně distribuována . Databáze orientované na dokumenty, zjednodušeně řečeno, spravují dokumenty, které nejsou ničím jiným než bezschemovým způsobem organizace polostrukturovaných dat . Spadají pod širší a volně definovaný deštník NoSQL databází, pojmenovaných po jejich zjevném odklonu od tradiční organizace SQL databází.
MongoDB poskytuje ovladače pro téměř všechny oblíbené programovací jazyky, jako je Java . Tyto ovladače nabízejí vrstvu abstrakce pro práci s MongoDB, takže nepracujeme přímo s protokolem Wire. Představte si to tak, že Oracle poskytuje implementaci ovladače JDBC pro svou relační databázi.
Pokud si však vzpomeneme na naše dny, kdy jsme pracovali s JDBC přímo, můžeme ocenit, jak to může být zamotané – zvláště v objektově orientovaném paradigmatu. Naštěstí máme k záchraně frameworky Object Relational Mapping (ORM), jako je Hibernate. U MongoDB se to příliš neliší.
I když můžeme jistě pracovat s ovladačem nízké úrovně, ke splnění úkolu to vyžaduje mnohem více standardů. Zde máme podobný koncept jako ORM s názvem Object Document Mapper (ODM) . Morphia přesně zaplňuje tento prostor pro programovací jazyk Java a pracuje nad ovladačem Java pro MongoDB.
3. Nastavení závislostí
Viděli jsme dost teorie, abychom se dostali do nějakého kódu. Pro naše příklady vymodelujeme knihovnu knih a uvidíme, jak ji můžeme spravovat v MongoDB pomocí Morphie.
Ale než začneme, budeme muset nastavit některé závislosti.
3.1. MongoDB
Abychom mohli pracovat, potřebujeme mít spuštěnou instanci MongoDB. Existuje několik způsobů, jak to získat, a nejjednodušší je stáhnout a nainstalovat komunitní edici na náš místní počítač.
Všechny výchozí konfigurace bychom měli ponechat tak, jak jsou, včetně portu, na kterém běží MongoDB.
3.2. Morphia
Můžeme si stáhnout předpřipravené JARy pro Morphia z Maven Central a použít je v našem projektu Java.
Nejjednodušší způsob je však použít nástroj pro správu závislostí, jako je Maven:
<dependency>
<groupId>dev.morphia.morphia</groupId>
<artifactId>core</artifactId>
<version>1.5.3</version>
</dependency>
4. Jak se připojit pomocí Morphia?
Nyní, když máme nainstalovanou a spuštěnou MongoDB a máme nastavenou Morphii v našem projektu Java, jsme připraveni se připojit k MongoDB pomocí Morphie.
Podívejme se, jak toho můžeme dosáhnout:
Morphia morphia = new Morphia();
morphia.mapPackage("com.baeldung.morphia");
Datastore datastore = morphia.createDatastore(new MongoClient(), "library");
datastore.ensureIndexes();
To je docela dost! Pojďme tomu lépe porozumět. Aby naše mapovací operace fungovaly, potřebujeme dvě věci:
- Mapovač:Zodpovídá za mapování našich Java POJO na kolekce MongoDB . V našem fragmentu kódu výše Morphia je za to odpovědná třída. Všimněte si, jak konfigurujeme balíček, kde by měl hledat naše POJO.
- Připojení:Toto je připojení k databázi MongoDB, na které může mapovač provádět různé operace. Třída Úložiště dat bere jako parametr instanci MongoClient (z ovladače Java MongoDB) a název databáze MongoDB, vrácení aktivního připojení k práci .
Takže jsme připraveni používat toto úložiště dat a spolupracovat s našimi subjekty.
5. Jak pracovat s entitami?
Než budeme moci použít náš čerstvě vyražený Datastore , musíme definovat některé entity domény, se kterými budeme pracovat.
5.1. Jednoduchá entita
Začněme definováním jednoduché Knihy entita s některými atributy:
@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
}
Zde je několik zajímavých věcí:
- Všimněte si anotace @Entita která kvalifikuje toto POJO pro mapování ODM od Morphia
- Morphia ve výchozím nastavení mapuje entitu do kolekce v MongoDB podle názvu její třídy, ale toto můžeme explicitně přepsat (jako jsme to udělali pro entitu Kniha zde)
- Morphia ve výchozím nastavení mapuje proměnné v entitě na klíče v kolekci MongoDB podle názvu proměnné, ale opět to můžeme přepsat (jako jsme to udělali u proměnné cost zde)
- Nakonec musíme označit proměnnou v entitě, která bude fungovat jako primární klíč, anotací @Id (jako když zde pro naši knihu používáme ISBN)
5.2. Subjekty se vztahy
Ve skutečném světě však entity nejsou tak jednoduché, jak vypadají, a mají mezi sebou složité vztahy. Například naše jednoduchá entita Kniha může mít Vydavatele a může odkazovat na další doprovodné knihy. Jak je modelujeme?
MongoDB nabízí dva mechanismy k budování vztahů — odkazování a vkládání . Jak název napovídá, s odkazováním MongoDB ukládá související data jako samostatný dokument ve stejné nebo jiné kolekci a pouze na ně odkazuje pomocí svého id.
Naopak při vkládání MongoDB ukládá nebo spíše vkládá vztah do samotného nadřazeného dokumentu.
Pojďme se podívat, jak je můžeme využít. Začněme vložením Vydavatele v naší Knize :
@Embedded
private Publisher publisher;
Dost jednoduché. Nyní pojďme do toho a přidejte odkazy na další knihy:
@Reference
private List<Book> companionBooks;
To je vše – Morphia poskytuje pohodlné anotace k modelování vztahů, jak je podporuje MongoDB. Volba odkazování vs. vkládání by však měla vycházet ze složitosti, redundance a konzistence datového modelu mimo jiné.
Cvičení je podobné normalizaci v relačních databázích.
Nyní jsme připraveni provést některé operace s Knihou pomocí Datastore .
6. Některé základní operace
Podívejme se, jak pracovat s některými základními operacemi pomocí Morphie.
6.1. Uložit
Začněme nejjednodušší z operací, vytvořením instance Book v naší databázi MongoDB knihovně :
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);
To stačí k tomu, aby Morphia mohla vytvořit kolekci v naší databázi MongoDB, pokud neexistuje, a provést operaci upsert.
6.2. Dotaz
Podívejme se, zda jsme schopni zadat dotaz na knihu, kterou jsme právě vytvořili v MongoDB:
List<Book> books = datastore.createQuery(Book.class)
.field("title")
.contains("Learning Java")
.find()
.toList();
assertEquals(1, books.size());
assertEquals(book, books.get(0));
Dotazování dokumentu v Morphii začíná vytvořením dotazu pomocí Datastore a poté deklarativním přidáním filtrů k radosti milovníků funkčního programování!
Morphia podporuje mnohem složitější konstrukci dotazů s filtry a operátory. Morphia navíc umožňuje omezit, přeskakovat a seřadit výsledky v dotazu.
A co víc, Morphia nám umožňuje používat nezpracované dotazy napsané pomocí ovladače Java pro MongoDB pro větší kontrolu, pokud by to bylo potřeba.
6.3. Aktualizovat
Ačkoli operace uložení může zpracovat aktualizace, pokud se primární klíč shoduje, Morphia poskytuje způsoby, jak selektivně aktualizovat dokumenty:
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());
Zde vytváříme dotaz a operaci aktualizace, abychom o jednu zvýšili cenu všech knih vrácených dotazem.
6.4. Smazat
Nakonec to, co bylo vytvořeno, musí být smazáno! S Morphií je to opět docela intuitivní:
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());
Dotaz vytvoříme zcela podobně jako dříve a spustíme operaci odstranění na Úložišti dat .
7. Pokročilé použití
MongoDB má některé pokročilé operace, jako je agregace, indexování a mnoho dalších . I když to není možné provést pomocí Morphie, je určitě možné něco z toho dosáhnout. Pro ostatní se bohužel budeme muset vrátit k ovladači Java pro MongoDB.
Zaměřme se na některé z těchto pokročilých operací, které můžeme provádět prostřednictvím Morphie.
7.1. Agregace
Agregace v MongoDB nám umožňuje definovat řadu operací v potrubí, které mohou pracovat se sadou dokumentů a produkovat agregovaný výstup .
Morphia má API pro podporu takového agregačního kanálu.
Předpokládejme, že si přejeme agregovat data naší knihovny takovým způsobem, abychom měli všechny knihy seskupené podle jejich autora:
Iterator<Author> iterator = datastore.createAggregation(Book.class)
.group("author", grouping("books", push("title")))
.out(Author.class);
Jak to tedy funguje? Začneme vytvořením agregačního kanálu pomocí stejného starého Datastore . Musíme poskytnout entitu, na které chceme provádět agregační operace, například Book zde.
Dále chceme seskupit dokumenty podle „autora“ a agregovat jejich „název“ pod klíčem nazvaným „knihy“. Konečně zde pracujeme s ODM. Musíme tedy definovat entitu, která bude shromažďovat naše agregovaná data – v našem případě je to Autor .
Samozřejmě musíme definovat entitu nazvanou Autor s proměnnou nazvanou knihy:
@Entity
public class Author {
@Id
private String name;
private List<String> books;
// other necessary getters and setters
}
To samozřejmě jen poškrábe povrch velmi výkonné konstrukce poskytované MongoDB a lze ji dále prozkoumat pro podrobnosti.
7.2. Projekce
Projekce v MongoDB nám umožňuje vybrat pouze pole, která chceme načíst z dokumentů v našich dotazech . V případě, že je struktura dokumentu složitá a těžká, může to být opravdu užitečné, když potřebujeme jen několik polí.
Předpokládejme, že potřebujeme získat pouze knihy s jejich názvem v našem dotazu:
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());
Zde, jak vidíme, získáme zpět pouze název v našem výsledku a nikoli autora a další pole. Měli bychom však být opatrní při používání projektovaného výstupu při ukládání zpět do MongoDB. To může vést ke ztrátě dat!
7.3. Indexování
Indexy hrají velmi důležitou roli při optimalizaci dotazů s databázemi – relačními i mnoha nerelačními.
MongoDB definuje indexy na úrovni kolekce s jedinečným indexem vytvořeným na primárním klíči ve výchozím nastavení . MongoDB navíc umožňuje vytvářet indexy pro libovolné pole nebo podpole v dokumentu. Měli bychom zvolit vytvoření indexu na klíči v závislosti na dotazu, který chceme vytvořit.
Například v našem příkladu si můžeme přát vytvořit index v poli „title“ Knihy jak se na to často ptáme:
@Indexes({
@Index(
fields = @Field("title"),
options = @IndexOptions(name = "book_title")
)
})
public class Book {
// ...
@Property
private String title;
// ...
}
Samozřejmě můžeme předat další možnosti indexování, abychom přizpůsobili nuance indexu, který se vytvoří. Všimněte si, že pole by mělo být označeno @Vlastností k použití v indexu.
Kromě indexu na úrovni třídy má Morphia navíc anotaci k definování indexu na úrovni pole.
7.4. Ověření schématu
Máme možnost poskytnout pravidla ověření dat pro kolekci, kterou může MongoDB použít při provádění aktualizace nebo operace vložení . Morphia to podporuje prostřednictvím svých API.
Řekněme, že nechceme vložit knihu bez platné ceny. K dosažení tohoto cíle můžeme využít ověření schématu:
@Validation("{ price : { $gt : 0 } }")
public class Book {
// ...
@Property("price")
private double cost;
// ...
}
Existuje bohatá sada ověření poskytovaných MongoDB, které lze použít zde.
8. Alternativní MongoDB ODM
Morphia není jediným dostupným MongoDB ODM pro Javu. Existuje několik dalších, které můžeme zvážit použití v našich aplikacích. Diskuse o srovnání s Morphií zde není možná, ale vždy je užitečné znát naše možnosti:
- Spring Data:Poskytuje jarní programovací model pro práci s MongoDB
- MongoJack:Poskytuje přímé mapování z JSON na objekty MongoDB
Toto není úplný seznam MongoDB ODM pro Javu, ale jsou k dispozici některé zajímavé alternativy!