So, you’ve got a project, and you’re trying to figure out which type of database to use—relational or non-relational?
Here’s the deal: neither is inherently better than the other. It really comes down to what you’re working with and what you need.
Relational databases (MySQL, PostgreSQL, and Oracle) are the veterans of the database world. They’ve been around forever and are fantastic for handling structured data. By structured, I mean data that’s nicely organized into tables with rows and columns, kind of like an Excel spreadsheet. You’ve got your tables, and they’re connected to each other through keys, which helps keep everything in sync.
Say you’re running a small online store. Your relational database might have a <span class="pink">Customers</span>
table that looks something like this:
Everything here is neat and tidy. Every customer has their own ID, and all their information fits perfectly into these predefined columns. Relational databases shine in scenarios like this because they keep your data clean, organized, and easy to query.
Now, let’s talk about non-relational databases like MongoDB, Cassandra, and DynamoDB. They’re built to handle unstructured or semi-structured data—stuff that doesn’t fit so neatly into rows and columns. Instead, these databases use formats like JSON, key-value pairs, or even graphs to store data.
On a social media platform like X, where users post tweets. Here's an example of what a tweet might look like in a non-relational database:
Above example of a tweet is just for a basic text tweet. But the challenge is that tweets are unpredicatable and can also include attachments like audio, video, or images, making the data more complex and unpredictable. Non-relational databases are ideal for handling this kind of unstructured data. They allow you to store diverse and varying information without needing a fixed schema. You can add or remove fields as necessary, making these databases highly adaptable to different data formats and requirements.
Scalability is a big one. Relational databases traditionally scale vertically, meaning you increase the power of a single server (more RAM, faster CPU) to handle more load. This can get expensive and might hit limits as your application grows. On the other hand, non-relational databases are designed to scale horizontally, meaning you can spread your database across multiple servers or nodes. This makes it easier and more cost-effective to handle massive amounts of data and high traffic.
Then there’s flexibility. Relational databases require a fixed schema, which means you need to define the structure of your data upfront. This can be limiting if your data structure is likely to change over time. Non-relational databases, on the other hand, are much more flexible since they don’t require a fixed schema. You can easily add new fields or change the structure of your data without major disruptions.
Transaction handling is also worth mentioning. Relational databases excel at handling transactions where consistency is crucial. If you’re working on a banking app, for example, you need to ensure that every transaction is processed accurately and consistently. While some NoSQL databases now offer transaction support, they’re generally more suited for scenarios where performance and availability are prioritized over strict consistency.
There’s no one-size-fits-all answer here. The best choice really depends on what you’re trying to achieve. In some cases, you might even want to use both—relational for the structured stuff and non-relational for everything else. The key is to understand your data and choose the tool that makes the most sense for your project.
In, this article we are going to discuss mongodb a popular NoSQL db and its integration with springboot.
MongoDB: An Introduction to Modern Databases
Collection and documents in Mongo DB
This image provides a visual comparison between how data is organized in a traditional relational database (RDBMS) and in MongoDB.
In MongoDB, collections and documents work a lot like tables and rows in a traditional SQL database, but with a bit more flexibility.
books</span>
collection, just like you’d have a <span class="pink">Books</span>
table in SQL.Books</span>
table where each row has columns like <span class="pink">Title</span>
, <span class="pink">Author</span>
, and <span class="pink">Year</span>
.books</span>
collection, each document would store the same information, but in a flexible format:
The Difference:
The big difference is that in SQL, every row in a table has to follow the same structure—every row needs to have the same columns. But in MongoDB, documents in a collection don’t have to look the same. One document might have an extra field or leave one out entirely, giving you more flexibility with how you structure your data.
💡 SpringBoot provides excellent support for MongoDB. In this article, we’ll cover everything related to Spring Boot projects using Maven.
When connecting a Spring Boot application with MongoDB, there are several approaches you can take, each with varying degrees of functionality and abstraction:
Spring Data MongoDB is the most straightforward and go-to approach to connecting a Spring Boot application with MongoDB. It provides an abstraction over MongoDB, allowing developers to interact with the database using repositories, similar to how they would with JPA.
You just need to add this dependency to your Spring Boot project:
For scenarios where you need complete control over how you interact with MongoDB, using the MongoDB Java Driver directly is a powerful approach. This method is especially useful when you want to bypass the abstractions provided by higher-level libraries and work directly with MongoDB's core features.
he key component of the MongoDB Java Driver is the <span class="pink">MongoClient</span>. This class acts as the main gateway to connect to your MongoDB instance. It manages the connection and allows you to perform operations on databases and collections.
When you use the <span class="pink">MongoClient</span>, you can access various databases and collections within MongoDB. This direct interaction lets you execute queries, insert documents, and handle other database operations with precise control. It’s especially beneficial for tasks that require specific database features or fine-tuned performance.
Understanding how to use <span class="pink">MongoClient</span> directly gives you a deeper insight into how MongoDB operations work under the hood. This knowledge is valuable because it helps you grasp how higher-level abstractions like <span class="pink">MongoRepository</span> and <span class="pink">MongoTemplate</span> in Spring Data MongoDB are built on top of the MongoDB Java Driver.
If your application demands high concurrency or non-blocking I/O, Spring WebFlux in combination with MongoDB’s reactive driver is a powerful option. It allows you to build reactive applications that can handle more traffic with fewer resources.
MongoDB Atlas is a cloud-based MongoDB service offering a fully managed solution. Connecting to Atlas is similar to connecting to a local MongoDB instance but involves using connection strings specific to your Atlas cluster.
Running MongoDB in a Docker container is a practical approach for managing your database during development or deployment. By using Docker, you can easily set up and isolate your MongoDB environment, ensuring consistency across different systems. Once MongoDB is running in a container, you can connect your Spring Boot application to it just as you would with a locally installed instance. This method is especially useful when you want to quickly spin up a MongoDB instance without going through the traditional installation process.
Each approach to connecting a spring application to a MongoDB instance has its strengths, and the right choice depends on your application's specific needs, such as the level of control you require, the complexity of your queries, and whether you're building a traditional or reactive application. Whether you're looking for simplicity or advanced control, Spring Boot provides versatile ways to connect with MongoDB.
Spring Data MongoDB builds upon MongoTemplate, which in turn uses the MongoDB Driver. The choice depends on the level of abstraction and specific features required for your application.
For reactive applications, Reactive MongoDB provides similar functionality to Spring Data MongoDB, but with support for non-blocking operations.
MongoDB Atlas and Docker focus on where and how MongoDB is hosted, rather than the connection method in your code. You would still use one of the other approaches to interact with the database, regardless of whether it's running locally, in the cloud, or in a container.
Objective: We will be developing a book management system using Spring Boot to create a RESTful API, with MongoDB as our data store. The primary focus of this project is to learn how to integrate MongoDB with Spring Boot, covering how to configure and interact with MongoDB in a Spring Boot application.
We'll create endpoints to manage books, including operations for adding, retrieving, updating, and deleting book records.
First, you'll need to create a new Spring Boot project. You can do this using Spring Initializr or directly from your IDE.
Dependencies to include:
Please note that we are working with Spring Boot 3, which requires a minimum of JDK 17.
Spring Data MongoDB focuses on ODM (Object-Document Mapping) for MongoDB., Spring Data MongoDB complements JPA by offering a similar level of abstraction and ease of use for MongoDB, while catering to the needs of NoSQL databases.
The <span class="pink">pom.xml</span> file should resemble the following:
configure MongoDB connection properties in your <span class="pink">application.properties</span>
Next, define a model class that maps to a MongoDB collection. This model will represent the data structure you’re working with in your API.
Book.java
<span class="pink">@Document</span>
: This annotation indicates that this class is a MongoDB document, and <span class="pink">collection</span>
specifies the name of the collection.<span class="pink">@Id</span>
: This annotation marks the primary key field in the document.
Understanding how MongoDB handles ID fields is crucial for effective database management. Here's a concise overview of the auto-generation behavior for different types of ID fields:
_id
</span>
Generation: MongoDB auto-generates an <span class="pink">_id</span>
field when not provided. By default, this is an <span class="pink">ObjectId</span>
, a unique identifier that ensures document uniqueness.private int id;
</span>
):private String id;
</span>
):String
IDs</span>, MongoDB can auto-generate values if configured as the <span class="pink">_id</span>
field, typically using its <span class="pink">ObjectId</span>
generator.ObjectId</span>
is a string representation that simplifies ID management and ensures uniqueness.ObjectId</span>
, are safer for ensuring unique identifiers.ObjectId</span>
strings are optimized for MongoDB's indexing and internal operations, providing better performance.ObjectId</span>
for simplicity and built-in support, which integrates seamlessly with MongoDB’s features.
Spring Data MongoDB allows you to interact with your database with minimal code by extending the <span class="pink">MongoRepository</span>
interface.
BookRepo.java
BookRepository</span>
interface extends <span class="pink">MongoRepository</span>
, providing simple CRUD operations and custom query methods.
Create a controller class to define RESTful API endpoints that interact with your MongoDB collection via the repository.
BookController.java
This <span class="pink">BookController</span> manages all book-related API requests. It handles everything from listing all books, retrieving a book by its ID, creating and updating books, to deleting them.
BookService.java
This <span class="pink">BookService</span> interface just handles the basics: fetching, adding, updating, or deleting books.
BookServiceImpl.java
The <span class="pink">BookServiceImpl</span> class implements the <span class="pink">BookService</span> interface and contains the actual code to manage books.
In MongoDB, the connection string is a URI (Uniform Resource Identifier) used by applications to connect to a MongoDB database. It specifies the database's location, authentication credentials, and other options to establish a connection. The format of the connection string is standardized and allows for various parameters to be included depending on the needs of your application.
Here’s a simple example of a MongoDB connection string:
This connection string connects to a MongoDB server running on <span class="pink">localhost</span>
at port <span class="pink">27018</span>
and uses the <span class="pink">gaurav</span>
database. The credentials <span class="pink">root</span>
as the username and <span class="pink">example</span>
as the password are provided for authentication.
In a Spring Boot application, you can specify the connection string in the <span class="pink">application.properties</span>
or <span class="pink">application.yml</span>
file like this:
This tells Spring Boot to connect to the <span class="pink">gaurav</span> database on the local MongoDB instance.
jdbc:mysql://localhost:3306/mydatabase</span>
where you connect to a MySQL database running on your computer on port 3306.mongodb://localhost:27017/gaurav</span>
connects to a MongoDB database running on your computer on port 27017.In both cases, the connection string tells your application where to find the database and which specific database to connect to.
Adding a new document to the books collection.
💡 Note: We won't be testing each API, but you are welcome to test them on your own, as they involve simple CRUD operations only.
For managing and interacting with MongoDB, several GUI tools are available:
MongoDB Compass is the official MongoDB tool offering data visualization, schema analysis, and indexing support for a comprehensive database management experience.
Robo 3T is a lightweight tool with an intuitive interface, shell integration, and query autocompletion, ideal for quick database interactions.
Studio 3T is a feature-rich tool with advanced capabilities like SQL to MongoDB migration, visual query building, and data import and export.
NoSQLBooster provides a rich query editor, IntelliSense support, and MongoDB shell integration for advanced querying and scripting.
Mongo Express is a web-based interface for basic database management, allowing CRUD operations and simple querying through a user-friendly browser interface.
and many more ….
MongoDB Compass is the official GUI tool provided by the MongoDB team for visualizing data, supporting indexing, creating databases, and more.
On the MongoDB Compass home page, simply enter your connection string to connect to your MongoDB instance.
MongoDB requires that a database contains at least one collection. Therefore, when you create a new database using MongoDB Compass, you must also add at least one collection to it.
In MongoDB, collections are not created until you insert the first document (record in SQL) into them. So even though you have a <span class="pink">Book</span> class annotated with <span class="pink">@Document(collection = "books")</span>, the <span class="pink">books</span> collection won't appear in your database until you actually save a <span class="pink">Book</span> object.
Create a database named "gaurav" and insert a book document into the "books" collection.
Explanation: On the left side, you can see a database named <span class="pink">gaurav</span>. When a book document is inserted, a collection called <span class="pink">books</span> is created. Inside this collection, you'll find the book document with <span class="pink">id=1</span>.
Now that the foundations are established, let us explore more in-depth advanced features.
MongoTemplate is a core component of Spring Data MongoDB, designed to make interactions with MongoDB more flexible and code-driven. It offers a higher level of abstraction for tasks like querying, updating, and deleting documents in MongoDB collections. Compared to the repository abstraction, MongoTemplate supports more complex and dynamic queries.
Earlier, we were using the <span class="pink">MongoRepository</span> interface, which offers a higher level of abstraction and simplifies basic CRUD operations. However, with <span class="pink">MongoTemplate</span>, we write our own queries for data operations directly within the service class methods. This approach gives us greater control over how we interact with our data.
Remove <span class="pink">BookRepo</span>
Since <span class="pink">MongoTemplate</span>
replaces the need for a repository interface, you can remove the <span class="pink">BookRepo</span>
interface.
Redefining the implementation class methods, with each method having its own custom query.
BookServiceImpl.java
To write custom queries with <span class="pink">MongoTemplate</span>
, one should focus on the following areas:
Query and Criteria API
Check out the <span class="pink">Query</span>
and <span class="pink">Criteria</span>
classes in Spring Data MongoDB. They let you build custom queries by defining conditions programmatically.
MongoDB Query Language (MQL)
Even though <span class="pink">MongoTemplate</span>
uses Java code rather than MongoDB’s native query language, knowing MQL can help you understand how to construct and translate complex queries.
MongoDB Aggregation Framework
For advanced queries, dive into MongoDB's Aggregation Framework. It’s great for tasks like grouping and sorting data, and you can use this knowledge to craft powerful queries with <span class="pink">MongoTemplate</span>
.
Setting up a MongoDB instance with Docker Compose is a quick and easy way to get your database running. Instead of dealing with tricky installations, you just use a simple configuration file to start MongoDB in a container. This makes it easy to manage your database, keep things consistent, and get up and running fast, whether you’re working on your local machine or preparing for deployment.
docker-compose.yml
This Docker Compose configuration deploys a MongoDB instance with the following setup:
<span class="pink">
version: '3.8'
</span>
: Specifies the Compose file format version 3.8.<span class="pink">
services
</span>
: Defines the <span class="pink">mongodb</span>
service:<span class="pink">
image: mongo:latest
</span>
: Utilizes the latest MongoDB image from Docker Hub.<span class="pink">
container_name: mongodb
</span>
: Assigns the container the name <span class="pink">mongodb</span>
.<span class="pink">
ports
</span>
: Maps host port <span class="pink">27018</span>
to container port <span class="pink">27017</span>
, facilitating database access.<span class="pink">
volumes
</span>
: Mounts the named volume <span class="pink">mongodb_data</span>
to <span class="pink">/data/db</span>
in the container for persistent storage.<span class="pink">
environment
</span>
: Configures MongoDB with a root username (<span class="pink">root</span>
) and password (<span class="pink">example</span>
).<span class="pink">
volumes
</span>
: Declares the <span class="pink">mongodb_data</span>
volume for storing MongoDB data persistently.
You can update the <span class="pink">application.properties</span>
file to connect your Spring Boot application to the MongoDB instance running inside the Docker container with the following URI:
The container named <span class="pink">springbootmongodb</span> is running, and it is running a MongoDB image inside.
When working with databases like MongoDB, the concept of linking collections becomes vital. While MongoDB's flexibility with schemas offers significant advantages, it also introduces unique challenges when managing linked collections.
In relational databases, relationships between tables are typically managed through foreign keys and joins. However, NoSQL databases like MongoDB do not have built-in join operations.
MongoDB lacks traditional joins found in SQL databases.
In this section, we extend our data model by introducing an additional document, <span class="pink">Publisher</span>
, which references the <span class="pink">Book</span>
document. This process demonstrates how to establish relationships between different collections in MongoDB, allowing for efficient data management and querying. By linking the <span class="pink">Book</span>
and <span class="pink">Publisher</span>
documents, we create a structured way to handle related information.
To facilitate this linkage, we utilize a <span class="pink">DataLoader</span>
class. This class is crucial for pre-populating the <span class="pink">Publisher</span>
collection with initial data. By doing so, we ensure that there are existing publisher records in the database that our <span class="pink">Book</span>
documents can reference. The <span class="pink">DataLoader</span>
automates the process of inserting sample data, making it easier to test and work with linked collections. This setup is essential for verifying the integrity of our references and ensuring that the data relationships function as intended.
Publisher.java
Explanation: Represents the <span class="pink">Publisher</span> document model in MongoDB with fields for <span class="pink">name</span>, <span class="pink">location</span>, and <span class="pink">contact<span>.
Book.java
Explanation: Defines the <span class="pink">Book</span>
document with a reference to a <span class="pink">Publisher</span>
, linking the two collections in MongoDB.
What <span class="pink">@DBRef
</span>
Does
@DBRef</span>
annotation indicates that the <span class="pink">publisher</span>
field in the <span class="pink">Book</span>
class is a reference to another document in a different collection, specifically the <span class="pink">Publisher</span>
collection. Instead of storing the entire <span class="pink">Publisher</span>
object within the <span class="pink">Book</span>
document, MongoDB stores a reference to the <span class="pink">Publisher</span>
document's ID.@DBRef</span>
is akin to normalizing a database in relational databases. It helps avoid duplication of data by storing only a reference to the <span class="pink">Publisher</span>
document rather than embedding the entire <span class="pink">Publisher</span>
object in every <span class="pink">Book</span>
document.How It Works
Book</span>
Class: When a <span class="pink">Book</span>
document is saved in MongoDB, the <span class="pink">publisher</span>
field will store a reference (a DBRef) pointing to the corresponding <span class="pink">Publisher</span>
document in the <span class="pink">Publisher</span>
collection.Publisher
</span> data is stored in a separate document within the <span class="pink">Publisher
</span> collection. When you retrieve a <span class="pink">Book</span> document, Spring Data MongoDB can automatically fetch the referenced <span class="pink">Publisher
</span> document using this DBRef.
PublisherRepo.java
DataLoader.java
Explanation: Loads initial <span class="pink">Publisher</span> data into the MongoDB database when the application starts.
MongoDB Atlas Vector Database is a specialized feature within MongoDB Atlas designed to handle vector data and perform efficient similarity searches, a key component for applications involving machine learning, natural language processing, and recommendation systems.
Key Highlights:
To integrate this into your Spring Boot project, simply add the following dependency:
MongoDB with Spring Boot is a vast topic that can't be fully explored in a single article. However, this article covers more than enough to get you started and running. We've covered key concepts, provided practical code examples, and highlighted important considerations. If any specific topics pique your interest, don’t hesitate to dive deeper and explore them further to enhance your understanding and skills.
Stay tuned for upcoming articles where we will dive into more advanced topics such as indexing, aggregation pipelines, caching, and connection pooling and much more.
Cheers!
Happy Coding.