Aasawari Sahasrabuddhe, Author at foojay https://foojay.io/today/author/aasawari-sahasrabuddhe/ a place for friends of OpenJDK Tue, 08 Jul 2025 19:08:25 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://foojay.io/wp-content/uploads/2020/04/Favicon-3-2-150x150.png Aasawari Sahasrabuddhe, Author at foojay https://foojay.io/today/author/aasawari-sahasrabuddhe/ 32 32 Building a Spring Boot CRUD Application Using MongoDB’s Relational Migrator https://foojay.io/today/building-a-spring-boot-crud-application-using-mongodbs-relational-migrator/ https://foojay.io/today/building-a-spring-boot-crud-application-using-mongodbs-relational-migrator/#comments Tue, 08 Jul 2025 19:05:43 +0000 https://foojay.io/?p=116792 Table of Contents Pre-requisitesRelational MigratorMigrating the data from the PostgreSQL schema to MongoDBAnalysing the Postgres schemaCreating mappings to generate the equivalent MongoDB schemaMigrating the data into MongoDBCode generation with Relational MigratorBuilding Spring Boot applicationExamples of aggregation pipelinesConclusion Imagine this: You’re ...

The post Building a Spring Boot CRUD Application Using MongoDB’s Relational Migrator appeared first on foojay.

]]>
Table of Contents
Pre-requisitesRelational MigratorMigrating the data from the PostgreSQL schema to MongoDBCode generation with Relational MigratorBuilding Spring Boot applicationConclusion

Imagine this: You’re working with a relational database that’s served you well for years, but now your applications demand flexibility, scalability, and faster development cycles. Transitioning from structured tables to MongoDB’s dynamic, schema-less JSON documents might be daunting. That’s where MongoDB’s Relational Migrator becomes your secret weapon.

The Relational Migrator tool built by MongoDB no longer only supports migrating data from relational databases to MongoDB. Rather, it supports features like code generation and also a query converter that converts a relational database, such as a Postgres query, or queries from views and stored procedures, into a MongoDB query.

Relational Migrator is a free tool that leverages intelligent algorithms and Gen AI to solve the most common data modeling, code conversion, and migration challenges, reducing the effort and risk involved in migration projects.

In this tutorial, we’ll explore how to harness the power of Spring Boot to build a fully functional CRUD application on top of your modernized database using the Relational Migrator.

This guide will help modernize a legacy application built with relational databases into a complete application using MongoDB.

Let's get started!

Pre-requisites

Before we get into the actual implementation to build the application, below are the pre-requisites that you need to have:

  1. Relational Migrator—you can download the tool available for free using the MongoDB Tools download page
  2. The SQL schema script to create the Postgres database and tables
  3. Java 21 or above
  4. The IDE of your choice
  5. A free Atlas cluster—create your first Atlas cluster for free

Relational Migrator

The Relational Migrator is a tool developed by MongoDB that helps you migrate data from a relational database into MongoDB. It is an application with a UI that helps you map the data from the relational schema to the MongoDB schema.

Along with providing migration capability, the tool offers more than the name suggests.

  1. Generate the application code: After the data has been migrated into the Atlas cluster, the developer asks how we begin the text. Well! The code generation feature of the RM tool is the answer to the questions. This allows you to get the boilerplate code for performing the basic CRUD operations and also expand the project to perform other complex functionality based on the project requirements.
  2. Query converter: The tool's query converter feature helps you convert your SQL queries, views, and stored procedures into equivalent MongoDB queries and validate them. The query converter uses the relational schema, the MongoDB schema, and the mapping rules in your current project to determine how the queries should be converted. Conversions may fail or be incorrect if the queries reference tables that are not in your relational schema or if they are not mapped to MongoDB collections. This query converter also works for views and stored procedures.

Migrating the data from the PostgreSQL schema to MongoDB

Once your free Atlas cluster is ready, download the SQL schema script, which has a sample Postgres schema with data inserted into the tables. Use the PgAdmin application to upload the schema and explore the created schema. The sample schema created nine different tables and their relationships for this tutorial. We will use the same schema to generate the equivalent and simpler MongoDB schema, following the different design patterns. First, let's examine both schemas in detail and then understand how to convert them to the equivalent MongoDB schema for further application development.

Analysing the Postgres schema

In this section, we will understand an example of a library management system where we have nine different tables, and the relationship between them is shown in the diagram below:

Image representing the relational schema diagram for the database

The ER diagram above also depicts the relationship between these tables. Relational databases often require intricate joins, nested subqueries, and multiple layers of aggregation to retrieve even moderately complex data relationships. As a result, what might seem like a simple query can quickly escalate into a large, complex, and unwieldy SQL statement. This not only increases the cognitive load for developers but also makes the code harder to maintain and prone to errors.

For example, let’s consider a scenario where we need to list all authors with their aliases.

To do so, we would write the SQL query as:

SELECT a.name, aa.alias
FROM library.authors a
LEFT JOIN library.author_alias aa ON a.id = aa.author_id;

This leads to the joining of two different tables using the foreign key constraint. In the next section, we will understand how this query would look in MongoDB.

Creating mappings to generate the equivalent MongoDB schema

The nine different tables in the relational schema need to be converted into five different collections using the mapping technique given by MongoDB. These techniques follow the design patterns followed by MongoDB in data modelling concepts.

After the mappings have been applied to the tables, the MongoDB schema would like the following:

Image representing the desired MongoDB schema

Let's try to convert the above SQL query into the equivalent MongoDB query:

db.collection.aggregate([
{
$project: {
"name": 1,
"aliases": 1,
"_id": 0
}
}
]
)

This is one such example where a huge ER diagram with nine different tables can be combined to form five different collections and make the query simpler.

After applying the mapping techniques, once the desired MongoDB schema is achieved, the next step is to migrate the data into the MongoDB Atlas cluster.

Migrating the data into MongoDB

To migrate the data into the cluster, click on “Data Migration” and select “Create Job Migration.”

To begin the migration, you should have the host as the relational database connection secure with you, and the destination is where you can apply the MongoDB connection string. Once both the source and the destination databases are all set up, the next step would be to select the type of migrations.

In MongoDB, Relational Migrator offers two types of migrations:

  1. Continuous migrations: Continuous migration jobs cover new incoming data with a zero-downtime change data capture (CDC) migration strategy.
  2. Snapshot migration: This only runs once and usually does a point-in-time migration.

After selecting the appropriate migration job based on your requirements, the next step is to click on “Review Summary” and then “Start.” The migration process will take some time, depending on the size of your data.

Once the migration is complete, you'll find your data seamlessly transferred to the MongoDB Atlas cluster. However, this is often the point where developers encounter uncertainty about what to do next.

But don’t worry—MongoDB Relational Migrator eliminates that confusion.

The tool’s Code Converter feature is designed to simplify your journey further by providing boilerplate code in the programming language of your choice. This makes it easy to jumpstart your application development, so you can focus on building great features without worrying about the groundwork.

Code generation with Relational Migrator

To create an application with migrated data using Relational Migrator, you should click on the “Code Generation” tab and select the language and template as Java and Spring Data, respectively. The below screenshot from the Relational Migrator tools explains the steps for the code generation.

Screenshot from Relational Migrator tool performing the code generation

Once you select the framework, you are all set to download/copy the code in the editor of your choice for further processing.

Building Spring Boot application

At this point, building the application becomes very easy, as all the essential code is provided. You just need to perform the business logic, and the application is all set to fulfil the requirements.

In this tutorial, we are using IntelliJ as the IDE and copying all the code provided by the Relational Migrator into a new Spring Boot project created using the Spring Initializr.

Depending on the data model that has been selected, the Relational Migrator tools create the entity and the repository files for the application.

Once the entity and the repository files are all copied/downloaded, all you need to do is create the service and the controller to perform the business logic of the applications. After all the files are copied, the project will look like this:

Screenshot from InteliJ representing the project structure of the application

The controller has all the REST API calls, and the service files are where we need to write the aggregate pipelines.

Let us understand a few examples in the next section.

Examples of aggregation pipelines

At this point in the application development, we have all the entity and repository files required for building the complete application.

Let us take an example where you need to find all books reviewed within a specific date range. To perform so in the Postgres query, you would have the query as:

SELECT 
    r.timestamp,
    u.name AS reviewer_name,
    b.title AS book_title,
    r.rating,
    r.text
FROM 
    library.reviews r
JOIN 
    library.books b ON r.book_id = b.id
JOIN 
    library.users u ON r.user_id = u.id
WHERE 
    r.timestamp BETWEEN '2022-01-01' AND '2024-12-31'
ORDER BY 
    r.timestamp ASC;

The equivalent MongoDB Java query in the schema can simply be written as:

public List<ReviewsEntity> getBookReviews() {
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(Criteria.where("timestamp")
                        .gte(new java.util.Date(1640995200000L))
                        .lte(new java.util.Date(1735603200000L))),
                Aggregation.lookup("books", "_id.bookId", "_id", "book"),
                Aggregation.unwind("book"),
                Aggregation.project()
                        .and("timestamp").as("timestamp")
                        .and("book.title").as("bookTitle")
                        .and("rating").as("rating")
                        .and("text").as("text"),
                Aggregation.sort(Sort.by(Sort.Direction.ASC, "timestamp"))
        );

        AggregationResults<ReviewsEntity> result = mongoTemplate.aggregate(
                aggregation,
                "reviews",
                ReviewsEntity.class
        );
        return result.getMappedResults();
    }

Similarly, a simple query can get an alias name for the author, for which the Postgres query can be written as below:

SELECT a.name, aa.alias
FROM library.authors a
LEFT JOIN library.author_alias aa ON a.id = aa.author_id;

This Postgres query can be simply used in MongoDB using the $project stage as:

public List<AuthorAlias> getAuthorAliases() {
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.project()
                        .andInclude("name", "authorAliases")
                        .andExclude("_id")
        );
        AggregationResults<AuthorAlias> result = mongoTemplate.aggregate(
                aggregation,
                "authors",
                AuthorAlias.class
        );
        return result.getMappedResults();
    }

More such examples are provided in the GitHub repository, which you can use and extend to perform more functionalities.

This tutorial therefore explains how to leverage the Relational Migrator and its functionality to create applications with no complexity and where the focus is more on the business logic and less on the boilerplate repetitive code.

Conclusion

This article shows how transitioning from traditional relational databases to MongoDB’s dynamic and schema-less architecture can be overwhelming, but MongoDB’s Relational Migrator simplifies the process. This tool facilitates seamless data migration and offers advanced features like SQL-to-MongoDB query conversion and automatic boilerplate code generation. In a practical tutorial, the article demonstrates how to modernize a legacy relational database-driven application into a Spring Boot-based CRUD application using MongoDB and Relational Migrator. By converting a sample relational schema into an optimized MongoDB schema, the tool reduces the complexity of joins and nested queries, paving the way for faster and more intuitive development cycles.

The guide further explores the step-by-step implementation, from migrating data into MongoDB Atlas using Snapshot or Continuous Migration strategies to generating ready-to-use application code for CRUD operations. The Relational Migrator provides a streamlined workflow for developers by offering code templates compatible with Java and Spring Data, making it easy to build on top of the migrated database. Additionally, the article showcases how MongoDB’s aggregation framework simplifies queries, such as filtering reviews within a date range or retrieving authors with aliases, compared to SQL. With examples and practical insights, this tutorial empowers developers to create scalable, modern applications effortlessly.

If you have any questions related to the article or you wish to learn more about MongoDB concepts, please visit the MongoDB community forums for the latest updates.

The post Building a Spring Boot CRUD Application Using MongoDB’s Relational Migrator appeared first on foojay.

]]>
https://foojay.io/today/building-a-spring-boot-crud-application-using-mongodbs-relational-migrator/feed/ 1
Data Modeling for Java Developers: Structuring With PostgreSQL and MongoDB https://foojay.io/today/data-modeling-for-java-developers-structuring-with-postgresql-and-mongodb/ https://foojay.io/today/data-modeling-for-java-developers-structuring-with-postgresql-and-mongodb/#comments Thu, 03 Jul 2025 21:02:16 +0000 https://foojay.io/?p=116770 Table of Contents Relationships in databases One-to-one relationship One-to-many relationship Many-to-many relationship Relational vs. document databasesPostgres implementation with JavaMongoDB implementation with JavaScalability and performanceMigration considerations Rethinking schema design Replacing joins with aggregations Conclusion Application and system designs have always been ...

The post Data Modeling for Java Developers: Structuring With PostgreSQL and MongoDB appeared first on foojay.

]]>
Table of Contents
Relationships in databasesRelational vs. document databasesPostgres implementation with JavaMongoDB implementation with JavaScalability and performanceMigration considerationsConclusion

Application and system designs have always been considered the most essential step in application development. All the later steps and technologies to be used depend on how the system has been designed. If you are a Java developer, choosing the right approach can mean distinguishing between a rigid, complex schema and a nimble, scalable solution. If you are a Java developer who works with PostgreSQL or other relational databases, you understand the pain of representing the many-to-many relationships between the tables.

This tutorial will ease your pain with these or other relationships defined in databases by making use of a document database, MongoDB.

In this article, we’ll understand both approaches, contrasting PostgreSQL’s relational rigour with MongoDB’s document-oriented simplicity. You’ll learn how to weigh trade-offs like ACID compliance versus scalability and discover why MongoDB’s design might save you time.

Relationships in databases

Relationships in databases introduce the connection between the entities of two or more different collections or tables. These relationships help the applications to have the dependencies interlinked with each other. To understand this in brief, let’s look at an example of a library management system that has tables for authors, books, issue details, etc. inside the database.

One-to-one relationship

Each record in Table A is related to only one record in Table B. Example: A Library Member table and an Issue Details table can have a one-to-one relationship, where each member can have only one active book issued at a time.

One-to-many relationship

A single record in Table A can be related to multiple records in Table B. For instance, a Book can have many Reviews or a user can have many contact addresses.

Many-to-many relationship

In this type of relationship, multiple records in Table A can relate to various records in Table B, requiring a junction (or bridge) table. For example, a Book can be issued to multiple Members over time, and a Member can borrow numerous Books.

Relational vs. document databases

A relational database is based on rigid predefined schemas and emphasises relationships. These work well when the structure is strict and is not subjected to much change in the future. SQL or MySQL has been the backbone of relational databases for many years now.

Whether you’re organizing customer contacts or powering complex financial systems, SQL’s straightforward yet powerful commands have made it a go-to tool for businesses worldwide—and it’s been that way for decades. Relational databases thrive on flexibility, adapting to everything from small-scale apps to enterprise-level solutions. That’s why industries of all kinds, from retail to healthcare, rely on them to store, manage, and make sense of their data. Think of SQL as the quiet workhorse behind the scenes, keeping everything running smoothly.

A document database, on the other hand, is meant for a more flexible structure. They work well with modern applications where a variety of data is stored and processed from the applications. A document database represents data as documents, typically using formats like JSON (JavaScript object notation) or BSON (Binary JSON). A document database is often referred to as a NoSQL database.

MongoDB is the most popular database used in modern application development. The flexible storage capability allows the application to scale horizontally and grow efficiently with the rapid changes.

Postgres implementation with Java

To understand how data in a Postgres database would be implemented with Java, let us consider an example ER diagram for a library management system consisting of Books, Authors, and Issue Details.

The ER diagram below depicts the one-to-many relationship between Books and Issue Details and the many-to-many relationship between Author and Books using the Author_Books table created using join operations.


Fig: ER diagram for the library management system using four different tables

Now, let us try to understand how these entities will be represented using the Java Hibernate code and the relationship annotations.

Let's first understand the Author representing the Author entity:

@Entity
public class Author {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long authorID;

    private String name;
    private String email;
    private String nationality;

    @ManyToMany(mappedBy = "authors", cascade = CascadeType.ALL)
    private Set<Book> books;
}

Similarly, the Books entity would be represented as:

@Entity
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long bookID;

    private String title;
    private String isbn;
    private String genre;
    private int publishedYear;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(
        name = "author_books",
        joinColumns = @JoinColumn(name = "bookID"),
        inverseJoinColumns = @JoinColumn(name = "authorID")
    )
    private Set<Author> authors;

    @OneToMany(mappedBy = "book", cascade = CascadeType.ALL)
    private Set<IssueDetails> issueDetails;

    //Getters and Setters
}

Now, the Author_books table has been created using the join methods and hence, we do not need to define a separate entity class.

The relationship between the entities has been established using the relationship annotations like @ManytoMany.

Similarly, to represent the one-to-many relationship between Books and the Issue Details using the @OneToMany annotation, we can write the entity class as:

@Entity
public class IssueDetails {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long issueID;

    @ManyToOne
    @JoinColumn(name = "bookID", nullable = false)
    private Book book;

    private Long userID;
    private Date issueDate;
    private Date returnDate;
    private String status;

    // Getters and Setters
}

The relationships implemented in the above code snippet could be very simple. If you are wondering how, the answer to this is in the next section where we will understand how simple it can be to use MongoDB as the database.

MongoDB implementation with Java

Let us understand the representation in a simpler way using the MongoDB document model and its data modelling techniques.

For example, representing the many-to-many relationship between the authors and books can be done using embedding or referencing data modelling techniques.

It is also important to note that if authors and books are frequently queried together, embedding author references within books or vice versa might be efficient. However, since an author can write many books and a book can have multiple authors, embedding might lead to duplication. So maybe using references with arrays of author IDs in books and book IDs in authors would be better. But that could complicate updates if an author's information changes. Alternatively, just using an array of author IDs in the book documents and not maintaining the inverse in authors might suffice, depending on query needs.

Depending on the modelling technique chosen, the documents inside in the collection would change. For example:

{
  _id: ObjectId("60d5ec9f4b1a8e2a1c8f7a1"), 
  name: "J.K. Rowling",
  email: "jkrowling@example.com",
  nationality: "British",
  books: [
    ObjectId("60d5ec9f4b1a8e2a1c8f7a2"), 
    ObjectId("60d5ec9f4b1a8e2a1c8f7a3")
  ]
}

The book collection would look like the below:

{
  _id: ObjectId("60d5ec9f4b1a8e2a1c8f7a2"), 
  title: "Harry Potter and the Sorcerer's Stone",
  isbn: "9780590353427",
  genre: "Fantasy",
  publishedYear: 1997,
  authors: [
    ObjectId("60d5ec9f4b1a8e2a1c8f7a1") 
  ],
  issues: [
    {
      userId: ObjectId("60d5ec9f4b1a8e2a1c8f7a4"), 
      issueDate: ISODate("2023-10-01"),
      returnDate: ISODate("2023-10-15"),
      status: "Returned"
    }
  ]
}

As you can see from the above example, the document model of MongoDB is similar to the POJOs representation in Java. Therefore, the representation of the model class becomes simpler with Java.

For example, the author class in Java would be written as:

@Document(collection = "authors")
public class Author {
    @Id
    private ObjectId id;
    private String name;
    private String email;
    private String nationality;
    private List<Book> bookIds; 
    //Getters and Setters
}

The book class can be written as:

@Document(collection = "books")
public class Book {
    @Id
    private ObjectId id;
    private String title;
    private String isbn;
    private String genre;
    private int publishedYear;
    private List<Author> authorIds;
    //  Getters and Setters
}

From the above code snippet, you can see cleaner and less complex code without any complicated annotations to represent the relationships.

Scalability and performance

After the demonstration of a few small code snippets from both databases, it is also important to understand the scalability and the performance considerations while creating a Java application.

We have all heard by now that Postgres is a powerful relational database that handles the structured query, but what does it do when an application needs to be scaled? Postgres scales vertically, which involves upgrading the hardware of a single server (e.g., adding more CPU, RAM, or storage). This approach is ideal for applications with predictable growth and moderate traffic. Still, it comes with limitations as hardware upgrades can become expensive, and there’s a physical ceiling to how much a single server can handle.

On the other hand, MongoDB is designed for scalability and high performance, especially regarding unstructured data and modern applications. MongoDB performs scalability using horizontal scaling, which means distributing data across multiple servers. This process in MongoDB is known as sharding, and the shards are created by selecting the right and appropriate shard key. Additionally, MongoDB optimizes read and write throughput through features like replica sets (for read scaling) and batch operations (for write scaling).

The performance of Java applications with MongoDB is optimised using demoralizations and indexing. Embedding and referencing the data reduces the need for expensive joins and enhances the query and application performance.

Migration considerations

When you migrate the data from Postgres to MongoDB, the process involves more than just moving the data. It specifically requires you to think about the structuring of the data and also how to manage the data. In the next section, we’ll talk about those briefly.

Rethinking schema design

In a relational database like Postgres, data is often normalised across multiple tables—in our case, between Authors, Books, and Issue Details. In MongoDB, we need to combine the related data into embedded documents. For example, instead of storing authors and books in separate tables, you can embed author information directly within a book document.

@Document(collection = "books")
public class Book {
    private String title;
    private List<Author> authors; // Embedded authors
    private List<IssueDetails> issues; // Embedded issues
}

Replacing joins with aggregations

Postgres makes use of joins to retrieve the related data. On the other hand, MongoDB relies mostly on writing aggregation pipelines to retrieve the related information. For example, a Postgres query might be:

SELECT books.title, authors.name 
FROM books 
JOIN author_books ON books.book_id = author_books.book_id 
JOIN authors ON author_books.author_id = authors.author_id;

This could simply be done using the Java code using the aggregation as:

Document lookupStage = new Document("$lookup", new Document("from", "authors") .append("localField", "authors") .append("foreignField", "_id") .append("as", "authorDetails") ); 
AggregateIterable<Document> result = booksCollection.aggregate(Arrays.asList(lookupStage)); 

Conclusion

Data modelling is a crucial step in application development and selecting the right database can significantly impact the scalability, performance, and maintainability of the system. For Java developers, identifying the strengths and weaknesses of the relational and non-relational databases is essential to correctly structure and manage the data.

From this tutorial, we have understood that PostgreSQL, with its relational model, excels in scenarios requiring complex queries, ACID compliance, and structured data. Its ability to handle relationships through joins and enforce constraints makes it ideal for applications like financial systems, ERP platforms, and reporting tools. However, its reliance on vertical scaling can become a limitation as applications grow.

On the other hand, MongoDB’s data document model offers greater flexibility, scalability, and higher performance, which makes it a great fit for modern applications. Its ability to handle unstructured data and scale horizontally allows developers to build nimble, scalable solutions without the rigidity of a predefined schema.

MongoDB’s document model becomes a natural fit for the unstructured data in modern applications, offering Java developers the ability to store, query, and manipulate complex data without rigid schemas. With powerful indexing, aggregation pipelines, and native support for JSON-like BSON documents, MongoDB simplifies data access, transformations, and manipulation easier. Whether handling product catalogues, customer interactions, or AI-driven insights, MongoDB empowers Java developers to build scalable, high-performance applications with minimal friction.

The post Data Modeling for Java Developers: Structuring With PostgreSQL and MongoDB appeared first on foojay.

]]>
https://foojay.io/today/data-modeling-for-java-developers-structuring-with-postgresql-and-mongodb/feed/ 1