eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – Summer Sale 2026 – NPI EA (cat= Baeldung)
announcement - icon

Yes, we're now running our only Summer Sale. All Courses are 30% off until 20th July, 2026:

>> EXPLORE ACCESS NOW

Course – Summer Sale 2026 – NPI (cat=Baeldung)
announcement - icon

Yes, we're now running our only Summer Sale. All Courses are 30% off until 20th July, 2026:

>> EXPLORE ACCESS NOW

1. Overview

In this tutorial, we’ll understand how to use Morphia, an Object Document Mapper (ODM) for MongoDB in Java.

In the process, we’ll also understand what is an ODM and how it facilitates working with MongoDB.

2. What Is an ODM?

For those uninitiated in this area, MongoDB is a document-oriented database built to be distributed by nature. Document-oriented databases, in simple terms, manage documents, which are nothing but a schema-less way of organizing semi-structured data. They fall under a broader and loosely defined umbrella of NoSQL databases, named after their apparent departure from the traditional organization of SQL databases.

MongoDB provides drivers for almost all popular programming languages like Java. These drivers offer a layer of abstraction for working with MongoDB so that we aren’t working with Wire Protocol directly. Think of this as Oracle providing an implementation of the JDBC driver for their relational database.

However, if we recall our days working with JDBC directly, we can appreciate how messy it can get — especially in an object-oriented paradigm. Fortunately, we have Object Relational Mapping (ORM) frameworks like Hibernate to our rescue. It isn’t very different for MongoDB.

While we can certainly work with the low-level driver, it requires a lot more boilerplate to accomplish the task. Here, we’ve got a similar concept to ORM called Object Document Mapper (ODM). Morphia exactly fills that space for the Java programming language and works on top of the Java driver for MongoDB.

3. Setting up Dependencies

We’ve seen enough theory to get us into some code. For our examples, we’ll model a library of books and see how we can manage it in MongoDB using Morphia.

But before we begin, we’ll need to set-up some of the dependencies.

3.1. MongoDB

We need to have a running instance of MongoDB to work with. There are several ways to get this, and the simplest is to download and install community edition on our local machine.

We should leave all default configurations as-is, including the port on which MongoDB runs.

3.2. Morphia

We can download the pre-built JARs for Morphia from Maven Central and use them in our Java project.

However, the simplest way is to use a dependency management tool like Maven:

<dependency>
    <groupId>dev.morphia.morphia</groupId>
    <artifactId>morphia-core</artifactId>
    <version>2.0.0</version>
</dependency>

4. How to Connect Using Morphia?

Now that we have MongoDB installed and running and have set-up Morphia in our Java project, we’re ready to connect to MongoDB using Morphia.

Let’s see how we can accomplish that:

Datastore datastore = Morphia.createDatastore(MongoClients.create(), "library");
datastore.getMapper().mapPackages("com.baeldung.morphia");
datastore.ensureIndexes();

That’s pretty much it! Let’s understand this better. We need two things for our mapping operations to work:

  1. A Mapper: This is responsible for mapping our Java POJOs to MongoDB Collections. In our code snippet above, Morphia is the class responsible for that. Note how we’re configuring the package where it should look for our POJOs.
  2. A Connection: This is the connection to a MongoDB database on which the mapper can execute different operations. The class Datastore takes as a parameter an instance of MongoClient (from the Java MongoDB driver) and the name of the MongoDB database, returning an active connection to work with.

So, we’re all set to use this Datastore and work with our entities.

5. How to Work with Entities?

Before we can use our freshly minted Datastore, we need to define some domain entities to work with.

5.1. Simple Entity

Let’s begin by defining a simple Book entity with some attributes:

@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
}

There are a couple of interesting things to note here:

  • Notice the annotation @Entity that qualifies this POJO for ODM mapping by Morphia
  • Morphia, by default, maps an entity to a collection in MongoDB by the name of its class, but we can explicitly override this (like we’ve done for the entity Book here)
  • Morphia, by default, maps the variables in an entity to the keys in a MongoDB collection by the name of the variable, but again we can override this (like we’ve done for the variable cost here)
  • Lastly, we need to mark a variable in the entity to act as the primary key by the annotation @Id (like we’re using ISBN for our book here)

5.2. Entities with Relationships

In the real world, though, entities are hardly as simple as they look and have complex relationships with each other. For instance, our simple entity Book can have a Publisher and can reference other companion books. How do we model them?

MongoDB offers two mechanisms to build relationships — Referencing and Embedding. As the name suggests, with referencing, MongoDB stores related data as a separate document in the same or a different collection and just references it using its id.

Simple enough. Now let’s go ahead and add references to other books:

@Reference
private List<Book> companionBooks;

That’s it — Morphia provides convenient annotations to model relationships as supported by MongoDB. The choice of referencing vs embedding, however, should draw from data model complexity, redundancy, and consistency amongst other considerations.

The exercise is similar to normalization in relational databases.

Now, we’re ready to perform some operations on Book using Datastore.

6. Some Basic Operations

Let’s see how to work with some of the basic operations using Morphia.

6.1. Save

Let’s begin with the simplest of the operations, creating an instance of Book in our MongoDB database library:

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);

This is enough to let Morphia create a collection in our MongoDB database, if it does not exist, and perform an upsert operation.

6.2. Query

Let’s see if we’re able to query the book we just created in MongoDB:

Query<Book> books = datastore.find(Book.class)
  .filter("title", "Learning Java");
List<Book> books = StreamSupport
                .stream(booksQuery.spliterator(), true)
                .collect(Collectors.toList());
assertEquals(1, books.size());
assertEquals(book, books.get(0));

Querying a document in Morphia begins with creating a query using Datastore and then declaratively adding filters, to the delight of those in love with functional programming!

Morphia supports much more complex query construction with filters and operators. Moreover, Morphia allows for limiting, skipping, and ordering of results in the query.

What’s more, Morphia allows us to use raw queries written with the Java driver for MongoDB for more control, should that be needed.

6.3. Update

Although a save operation can handle updates if the primary key matches, Morphia provides ways to selectively update documents:

final Book execute = datastore.find(Book.class)
                .filter(eq("title", "Learning Java"))
                .modify(UpdateOperators.set("price", 4.95))
                .execute(new ModifyOptions().returnDocument(ReturnDocument.AFTER));
assertEquals(4.95, books.get(0).getCost());

Here, we’re building a query and an update operation to increase by one the price of all books returned by the query.

6.4. Delete

Finally, that which has been created must be deleted! Again, with Morphia, it’s quite intuitive:

datastore.find(Book.class)
                .filter(eq("title", "Learning Java"))
                .delete(new DeleteOptions().multi(true));
datastore.find(Book.class)
                .filter(eq("title", "Learning Java"))
                .delete(new DeleteOptions().multi(true));
assertEquals(0, books.size());

We create the query quite similarly as before and run the delete operation on the Datastore.

7. Advanced Usage

MongoDB has some advanced operations like Aggregation, Indexing, and many others. While it isn’t possible to perform all of that using Morphia, it’s certainly possible to achieve some of that. For others, sadly, we’ll have to fall back to the Java driver for MongoDB.

Let’s focus on some of these advanced operations that we can perform through Morphia.

7.1. Aggregation

Aggregation in MongoDB allows us to define a series of operations in a pipeline that can operate on a set of documents and produce aggregated output.

Morphia has an API to support such an aggregation pipeline.

Let’s assume we wish to aggregate our library data in such a manner that we have all the books grouped by their author:

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

So, how does this work? We begin by creating an aggregation pipeline using the same old Datastore. We have to provide the entity on which we wish to perform aggregation operations, for instance, Book here.

Next, we want to group documents by “author” and aggregate their “title” under a key called “books”. Finally, we’re working with an ODM here. So, we have to define an entity to collect our aggregated data — in our case, it’s Author.

Of course, we have to define an entity called Author with a variable called books:

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

This, of course, just scratches the surface of a very powerful construct provided by MongoDB and can be explored further for details.

7.2. Projection

Projection in MongoDB allows us to select only the fields we want to fetch from documents in our queries. In case document structure is complex and heavy, this can be really useful when we need only a few fields.

Let’s suppose we only need to fetch books with their title in our query:

List<Book> books = datastore.find(Book.class)
        .filter(eq("title", "Learning Java"))
        .iterator(new FindOptions().projection().include("title")).toList();
assertEquals("Learning Java", books.get(0).getTitle());
assertNull(books.get(0).getAuthor());

Here, as we can see, we only get back the title in our result and not the author and other fields. We should, however, be careful in using the projected output in saving back to MongoDB. This may result in data loss!

7.3. Indexing

Indexes play a very important role in query optimization with databases — relational as well as many non-relational ones.

MongoDB defines indexes at the level of the collection with a unique index created on the primary key by default. Moreover, MongoDB allows indexes to be created on any field or sub-field within a document. We should choose to create an index on a key depending on the query we wish to create.

For instance, in our example, we may wish to create an index on the field “title” of Book as we often end up querying on it:

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

Of course, we can pass additional indexing options to tailor the nuances of the index that gets created. Note that the field should be annotated by @Property to be used in an index.

Moreover, apart from the class-level index, Morphia has an annotation to define a field-level index as well.

7.4. Schema Validation

We’ve got an option to provide data validation rules for a collection that MongoDB can use while performing an update or insert operation. Morphia supports this through their APIs.

Let’s say that we don’t want to insert a book without a valid price. We can leverage schema validation to achieve this:

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

There is a rich set of validations provided by MongoDB that can be employed here.

8. Alternative MongoDB ODMs

Morphia is not the only available MongoDB ODM for Java. There are several others that we can consider to use in our applications. A discussion on comparison with Morphia is not possible here, but it is always useful to know our options:

  • Spring Data: Provides a Spring-based programming model for working with MongoDB
  • MongoJack: Provides direct mapping from JSON to MongoDB objects

This is not a complete list of MongoDB ODMs for Java, but there are some interesting alternates available!

9. Conclusion

In this article, we understood the basic details of MongoDB and the use of an ODM to connect and operate on MongoDB from a programing language like Java. We further explored Morphia as a MongoDB ODM for Java and the various capabilities it has.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

Course – Summer Sale 2026 – NPI EA (cat= Baeldung)
announcement - icon

Yes, we're now running our only Summer Sale. All Courses are 30% off until 20th July, 2026:

>> EXPLORE ACCESS NOW

Course – Summer Sale 2026 – NPI (All)
announcement - icon

Yes, we're now running our only Summer Sale. All Courses are 30% off until 20th July, 2026:

>> EXPLORE ACCESS NOW

eBook Jackson – NPI EA – 3 (cat = Jackson)