Inleiding tot Morphia - Java ODM voor MongoDB

1. Overzicht

In deze tutorial zullen we begrijpen hoe we Morphia, een Object Document Mapper (ODM) voor MongoDB in Java, kunnen gebruiken.

Tijdens het proces zullen we ook begrijpen wat een ODM is en hoe het het werken met MongoDB vergemakkelijkt.

2. Wat is een ODM?

Voor degenen die niet-ingewijden in dit gebied zijn, MongoDB is een documentgeoriënteerde database die is gebouwd om door de natuur te worden gedistribueerd. Documentgeoriënteerde databases beheren in eenvoudige bewoordingen documenten, die niets anders zijn dan een schemaloze manier om semi-gestructureerde gegevens te ordenen. Ze vallen onder een bredere en losjes gedefinieerde paraplu van NoSQL-databases, genoemd naar hun kennelijke afwijking van de traditionele organisatie van SQL-databases.

MongoDB biedt stuurprogramma's voor bijna alle populaire programmeertalen zoals Java. Deze stuurprogramma's bieden een abstractielaag voor het werken met MongoDB, zodat we niet rechtstreeks met Wire Protocol werken. Beschouw dit als Oracle dat een implementatie biedt van het JDBC-stuurprogramma voor hun relationele database.

Als we ons echter onze dagen herinneren dat we rechtstreeks met JDBC werkten, kunnen we begrijpen hoe rommelig het kan worden, vooral in een objectgeoriënteerd paradigma. Gelukkig hebben we Object Relational Mapping (ORM) -raamwerken zoals Hibernate om ons te redden. Het is niet heel anders voor MongoDB.

Hoewel we zeker kunnen werken met de low-level driver, is er veel meer standaard nodig om de taak te volbrengen. Hier hebben we een soortgelijk concept als ORM genaamd Object Document Mapper (ODM). Morphia vult precies die ruimte voor de programmeertaal Java en werkt bovenop de Java-driver voor MongoDB.

3. Afhankelijkheden instellen

We hebben genoeg theorie gezien om ons in een code te krijgen. Voor onze voorbeelden zullen we een bibliotheek met boeken modelleren en kijken hoe we deze in MongoDB kunnen beheren met Morphia.

Maar voordat we beginnen, moeten we enkele afhankelijkheden instellen.

3.1. MongoDB

We hebben een actief exemplaar van MongoDB nodig om mee te werken. Er zijn verschillende manieren om dit te krijgen, en de eenvoudigste is om de communityeditie op onze lokale computer te downloaden en te installeren.

We moeten alle standaardconfiguraties laten zoals ze zijn, inclusief de poort waarop MongoDB draait.

3.2. Morfine

We kunnen de voorgebouwde JAR's voor Morphia downloaden van Maven Central en ze gebruiken in ons Java-project.

De eenvoudigste manier is echter om een ​​hulpprogramma voor afhankelijkheidsbeheer zoals Maven te gebruiken:

 dev.morphia.morphia core 1.5.3 

4. Hoe maak je verbinding met Morphia?

Nu we MongoDB hebben geïnstalleerd en draaien en Morphia hebben opgezet in ons Java-project, zijn we klaar om verbinding te maken met MongoDB met behulp van Morphia.

Laten we eens kijken hoe we dat kunnen bereiken:

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

Dat is het eigenlijk wel! Laten we dit beter begrijpen. We hebben twee dingen nodig om onze kaartbewerkingen te laten werken:

  1. Een kaartenmaker: deze is verantwoordelijk voor het in kaart brengen van onze Java POJO's naar MongoDB Collections. In ons codefragment hierboven, Morfine is de klasse die daarvoor verantwoordelijk is. Merk op hoe we het pakket configureren waar het naar onze POJO's moet zoeken.
  2. Een verbinding: dit is de verbinding met een MongoDB-database waarop de mapper verschillende bewerkingen kan uitvoeren. De klas Datastore neemt als parameter een instantie van MongoClient (van het Java MongoDB-stuurprogramma) en de naam van de MongoDB-database, een actieve verbinding teruggeven om mee te werken.

Dus we zijn er helemaal klaar voor om dit te gebruiken Datastore en werken met onze entiteiten.

5. Hoe te werken met entiteiten?

Voordat we onze vers geslagen Datastore, moeten we enkele domeinentiteiten definiëren om mee te werken.

5.1. Eenvoudige entiteit

Laten we beginnen met het definiëren van een eenvoudig Boek entiteit met enkele attributen:

@Entity ("Boeken") openbare klasse Boek {@Id private String isbn; private String-titel; private String-auteur; @Property ("prijs") dubbele privékosten; // constructors, getters, setters en hashCode, equals, toString implementaties}

Er zijn een paar interessante dingen om op te merken:

  • Let op de annotatie @Entiteit die deze POJO kwalificeert voor ODM-mapping door Morphia
  • Morphia wijst standaard een entiteit toe aan een verzameling in MongoDB met de naam van zijn klasse, maar we kunnen dit expliciet negeren (zoals we hebben gedaan voor de entiteit Boek hier)
  • Morphia wijst standaard de variabelen in een entiteit toe aan de sleutels in een MongoDB-verzameling met de naam van de variabele, maar we kunnen dit opnieuw overschrijven (zoals we hebben gedaan voor de variabele kosten hier)
  • Ten slotte moeten we markeer een variabele in de entiteit om als de primaire sleutel te fungeren door de annotatie @ID kaart (alsof we hier ISBN gebruiken voor ons boek)

5.2. Entiteiten met relaties

In de echte wereld zijn entiteiten echter lang niet zo eenvoudig als ze eruitzien en hebben ze complexe relaties met elkaar. Bijvoorbeeld onze eenvoudige entiteit Boek kan een Uitgever en kan verwijzen naar andere begeleidende boeken. Hoe modelleren we ze?

MongoDB biedt twee mechanismen om relaties op te bouwen - Referencing en Embedding. Zoals de naam al doet vermoeden, slaat MongoDB met verwijzingen gerelateerde gegevens op als een afzonderlijk document in dezelfde of een andere verzameling en verwijst er alleen naar met behulp van de id.

Integendeel, met insluiten slaat MongoDB de relatie op, of liever gezegd, in het bovenliggende document zelf.

Laten we eens kijken hoe we ze kunnen gebruiken. Laten we beginnen met inbedden Uitgever in onze Boek:

@Embedded private Publisher-uitgever;

Simpel genoeg. Laten we nu doorgaan en verwijzingen naar andere boeken toevoegen:

@Reference privélijst companionBooks;

Dat is alles - Morphia biedt handige annotaties om relaties te modelleren, zoals ondersteund door MongoDB. De keuze van refereren versus insluiten moet echter putten uit de complexiteit, redundantie en consistentie van datamodellen onder andere overwegingen.

De oefening is vergelijkbaar met normalisatie in relationele databases.

Nu zijn we klaar om wat bewerkingen uit te voeren op Boek gebruik makend van Datastore.

6. Enkele basisbewerkingen

Laten we eens kijken hoe we met enkele basisbewerkingen kunnen werken met Morphia.

6.1. Sparen

Laten we beginnen met de eenvoudigste bewerkingen, door een instantie te maken van Boek in onze MongoDB-database bibliotheek:

Publisher publisher = nieuwe uitgever (nieuwe ObjectId (), "Awsome Publisher"); Boekboek = nieuw boek ("9781565927186", "Learning Java", "Tom Kirkman", 3,95, uitgever); Boek companionBook = nieuw boek ("9789332575103", "Java Performance Companion", "Tom Kirkman", 1,95, uitgever); book.addCompanionBooks (companionBook); datastore.save (companionBook); datastore.save (boek);

Dit is voldoende om Morphia een collectie in onze MongoDB-database te laten maken, als deze niet bestaat, en een upsert-bewerking uit te voeren.

6.2. Vraag

Laten we eens kijken of we het boek dat we zojuist hebben gemaakt in MongoDB kunnen bevragen:

List books = datastore.createQuery (Book.class) .field ("title") .contains ("Learning Java") .find () .toList (); assertEquals (1, books.size ()); assertEquals (boek, books.get (0));

Het opvragen van een document in Morphia begint met het maken van een zoekvraag met Datastore en vervolgens declaratief filters toevoegen, tot grote vreugde van liefhebbers van functioneel programmeren!

Morphia ondersteunt veel complexere queryconstructies met filters en operators. Bovendien staat Morphia het beperken, overslaan en ordenen van resultaten in de query toe.

Bovendien stelt Morphia ons in staat om onbewerkte query's te gebruiken die zijn geschreven met de Java-driver voor MongoDB voor meer controle, mocht dat nodig zijn.

6.3. Bijwerken

Hoewel een opslagbewerking updates kan verwerken als de primaire sleutel overeenkomt, biedt Morphia manieren om documenten selectief bij te werken:

Queryquery = datastore.createQuery (Book.class) .field ("title") .contains ("Learning Java"); UpdateOperations updates = datastore.createUpdateOperations (Book.class) .inc ("prijs", 1); datastore.update (query, updates); List books = datastore.createQuery (Book.class) .field ("title") .contains ("Learning Java") .find () .toList (); assertEquals (4.95, books.get (0) .getCost ());

Hier bouwen we een query en een updatebewerking om de prijs van alle boeken die door de query worden geretourneerd, met één te verhogen.

6.4. Verwijderen

Ten slotte moet dat wat is gemaakt, worden verwijderd! Nogmaals, met Morphia is het vrij intuïtief:

Queryquery = datastore.createQuery (Book.class) .field ("title") .contains ("Learning Java"); datastore.delete (zoekopdracht); List books = datastore.createQuery (Book.class) .field ("title") .contains ("Learning Java") .find () .toList (); assertEquals (0, books.size ());

We maken de query op dezelfde manier als voorheen en voeren de verwijderbewerking uit op het Datastore.

7. Geavanceerd gebruik

MongoDB heeft sommige geavanceerde bewerkingen zoals aggregatie, indexering en vele andere. Hoewel het niet mogelijk is om dat allemaal met Morphia uit te voeren, is het zeker mogelijk om een ​​deel daarvan te bereiken. Voor anderen zullen we helaas terug moeten vallen op de Java-driver voor MongoDB.

Laten we ons concentreren op enkele van deze geavanceerde operaties die we via Morphia kunnen uitvoeren.

7.1. Aggregatie

Aggregatie in MongoDB stelt ons in staat om te definiëren een reeks bewerkingen in een pijplijn die kunnen werken op een set documenten en geaggregeerde output kunnen produceren.

Morphia heeft een API om zo'n aggregatiepijplijn te ondersteunen.

Laten we aannemen dat we onze bibliotheekgegevens zo willen samenvoegen dat we alle boeken gegroepeerd hebben op hun auteur:

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

Dus, hoe werkt dit? We beginnen met het maken van een aggregatiepijplijn met dezelfde oude Datastore. We moeten de entiteit verstrekken waarop we aggregatiebewerkingen willen uitvoeren, bijvoorbeeld Boek hier.

Vervolgens willen we documenten groeperen op "auteur" en hun "titel" samenvoegen onder een sleutel genaamd "boeken". Ten slotte werken we hier met een ODM. We moeten dus een entiteit definiëren om onze geaggregeerde gegevens te verzamelen - in ons geval is dat Schrijver.

Natuurlijk moeten we een entiteit met de naam definiëren Schrijver met een variabele genaamd books:

@Entity openbare klasse Auteur {@Id privé Stringnaam; privélijstboeken; // andere noodzakelijke getters en setters}

Dit krast natuurlijk gewoon het oppervlak van een zeer krachtig construct geleverd door MongoDB en kan verder worden onderzocht voor details.

7.2. Projectie

Projectie in MongoDB stelt ons in staat selecteer alleen de velden die we willen ophalen uit documenten in onze zoekopdrachten. Als de documentstructuur complex en zwaar is, kan dit erg handig zijn als we maar een paar velden nodig hebben.

Laten we aannemen dat we alleen boeken met hun titel in onze zoekopdracht hoeven op te halen:

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

Hier krijgen we, zoals we kunnen zien, alleen de titel terug in ons resultaat en niet de auteur en andere velden. We moeten echter voorzichtig zijn bij het gebruik van de geprojecteerde uitvoer bij het opslaan naar MongoDB. Dit kan leiden tot gegevensverlies!

7.3. Indexeren

Indexen spelen een zeer belangrijke rol bij het optimaliseren van query's met databases - zowel relationele als veel niet-relationele.

MongoDB definieert indexen op het niveau van de verzameling met een unieke index die standaard op de primaire sleutel wordt gemaakt. Bovendien maakt MongoDB het mogelijk om indexen aan te maken op elk veld of subveld binnen een document. We moeten ervoor kiezen om een ​​index op een sleutel te maken, afhankelijk van de query die we willen maken.

In ons voorbeeld willen we bijvoorbeeld een index maken voor het veld "titel" van Boek zoals we er vaak over vragen:

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

Natuurlijk kunnen we aanvullende indexeringsopties doorgeven om de nuances van de index die wordt gemaakt aan te passen. Merk op dat het veld moet worden geannoteerd met @Eigendom om te worden gebruikt in een index.

Bovendien heeft Morphia, afgezien van de index op klassenniveau, een annotatie om ook een index op veldniveau te definiëren.

7.4. Schema-validatie

We hebben een optie te bieden gegevensvalidatieregels voor een verzameling die MongoDB kan gebruiken tijdens het uitvoeren van een update- of invoegbewerking. Morphia ondersteunt dit via hun API's.

Laten we zeggen dat we geen boek willen invoegen zonder een geldige prijs. We kunnen schemavalidatie gebruiken om dit te bereiken:

@Validation ("{price: {$ gt: 0}}") public class Book {// ... @Property ("price") privé dubbele kosten; // ...}

MongoDB biedt een uitgebreide reeks validaties die hier kunnen worden gebruikt.

8. Alternatieve MongoDB ODM's

Morphia is niet de enige beschikbare MongoDB ODM voor Java. Er zijn verschillende andere die we kunnen overwegen om in onze applicaties te gebruiken. Een discussie over vergelijking met Morphia is hier niet mogelijk, maar het is altijd handig om onze mogelijkheden te kennen:

  • Spring Data: biedt een op Spring gebaseerd programmeermodel voor het werken met MongoDB
  • MongoJack: biedt directe toewijzing van JSON naar MongoDB-objecten

Dit is geen volledige lijst van MongoDB ODM's voor Java, maar er zijn enkele interessante alternatieven beschikbaar!

9. Conclusie

In dit artikel hebben we de basisdetails van MongoDB begrepen en het gebruik van een ODM om verbinding te maken en te werken met MongoDB vanuit een programmeertaal als Java. We hebben Morphia verder onderzocht als een MongoDB ODM voor Java en de verschillende mogelijkheden die het heeft.

Zoals altijd is de code te vinden op GitHub.