Using Spring Data MongoDB with Oracle Database’s MongoDB API

Using Spring Data MongoDB with Oracle Database’s MongoDB API

MongoDB is a popular, open-source NoSQL database that stores data in a flexible, JSON-like format, making it ideal for handling large, unstructured, or semi-structured data.

The Oracle Database MongoDB API translates MongoDB client requests into SQL statements that are run by Oracle Database, allowing developers to easily use MongoDB clients with Oracle Database. The Oracle Database MongoDB API works best with release 22.3 or later of Oracle REST Data Services (ORDS)

In this article, we’ll implement a basic MongoRepository for Oracle Database demonstrating Oracle-MongoDB wire compatibility in the OracleMongoDBTest test class. Example operations for CRUD, querying, and MongoTemplate are included — each being identical to if you were actually using MongoDB.

Want to jump to the code? Find the full source here.

Configuring an Oracle Autonomous Database Instance

This example requires an Oracle Database instance with ORDS installed. The easiest way to do this is to configure an Oracle Autonomous Database for JSON processing, as described in the Using Oracle Database API for MongoDB document.

Once you’ve setup a database instance, save your database URI, username, and password before continuing to the next section.

Note that two free, license included Autonomous Database instances are included in OCI’s Always-Free tier.

Testing out MongoRepository with Oracle Database

For a given Student document, we can easily implement a Student MongoRepository:

package com.example.mongodb;

import java.util.List;
import java.util.Optional;

import org.springframework.data.mongodb.repository.MongoRepository;

public interface StudentRepository extends MongoRepository<Student, String> {
}        

Notice how only Spring Data MongoDB APIs are used? This module only depends on spring-data-mongodb — No Oracle dependencies are on the classpath. This also means you can switch MongoDB apps to use Oracle Database without changing your code.

Let’s try out our repository, implementing some basic test cases in the OracleMongoDBTest class. To run the test, you’ll need to to set the DB_USERNAME, DB_PASSWORD, and DB_URI environment variables from your database instance configured in the previous section.

In the test, we use standard Spring repository methods to create, update, query, and delete a student document. On the database backend, MongoDB requests are transparently converted to SQL and run by Oracle Database:

// The DB_USERNAME, DB_PASSWORD, and DB_URI environment variables must be set
// to run this test.
@EnabledIfEnvironmentVariables(value = {
        @EnabledIfEnvironmentVariable(named = "DB_USERNAME", matches = ".+"),
        @EnabledIfEnvironmentVariable(named = "DB_PASSWORD", matches = ".+"),
        @EnabledIfEnvironmentVariable(named = "DB_URI", matches = ".+")
})
@SpringBootTest
public class OracleMongoDBTest {
    @Autowired
    StudentRepository studentRepository;

    Student aliceSmith = new Student(
            UUID.randomUUID().toString(),
            "Alice Smith",
            "alice.smith@example.edu",
            10,
            45,
            3.77
    );

    Student johnDoe = new Student(
            UUID.randomUUID().toString(),
            "John Doe",
            "john.doe@example.edu",
            6,
            24,
            3.23
    );

    @Test
    void basicCRUDOperations() {
        // Simple CRUD repository actions work with Oracle Database.
        // Create a new student
        Student saved = studentRepository.save(aliceSmith);

        // Verify student is present and matches client student object.
        Optional<Student> byId = studentRepository.findById(saved.get_id());
        assertThat(byId.isPresent()).isTrue();
        assertThat(byId.get()).isEqualTo(aliceSmith);

        // Update the student and verify updated values.
        aliceSmith.setCredits(50);
        aliceSmith.setGpa(3.79);
        saved = studentRepository.save(aliceSmith);
        assertThat(saved.getCredits()).isEqualTo(50);
        assertThat(saved.getGpa()).isEqualTo(3.79);

        // Delete student and verify no longer present.
        studentRepository.deleteById(saved.get_id());
        byId = studentRepository.findById(saved.get_id());
        assertThat(byId.isPresent()).isFalse();
    }

    @AfterEach
    void cleanup() {
        studentRepository.deleteAll();
    }        

MongoRepository Custom Queries

Let’s add MongoRepository custom queries to our StudentRepository to try it out with Oracle Database. The custom queries use Spring or Mongo syntax to build predicates, are don’t rely on Oracle SQL syntax.

package com.example.mongodb;

import java.util.List;
import java.util.Optional;

import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;

public interface StudentRepository extends MongoRepository<Student, String> {
    Optional<Student> findByEmail(String email);

    @Query("{ 'course_count': { $gte: ?0, $lte: ?1 } }")
    List<Student> findByCourseCountInRange(int minCourses, int maxCourses);

    @Query(value = "{ credits: { $gte:  ?0 } }", fields = "{ 'email': 1 }")
    List<Student> findStudentEmailsWhereCreditsGreaterThan(int minCredits);
}        

Next, we add a test case to OracleMongoDBTest that verifies the custom queries work as expected:

    @Test
    void queryOperations() {
        // Repository query options also work with Oracle Database.
        studentRepository.save(aliceSmith);
        studentRepository.save(johnDoe);

        // Query by email address.
        assertThat(studentRepository.findByEmail("john.doe@example.edu")
                .isPresent())
                .isTrue();

        // Query by course count.
        List<Student> byCourseCountInRange = studentRepository.findByCourseCountInRange(8, 12);
        assertThat(byCourseCountInRange.size()).isEqualTo(1);
        assertThat(byCourseCountInRange.getFirst()).isEqualTo(aliceSmith);

        // Query students, only returning the email.
        List<Student> studentEmails = studentRepository.findStudentEmailsWhereCreditsGreaterThan(0);
        assertThat(studentEmails).hasSize(2);
        studentEmails.forEach(student -> {
            assertThat(student.getName()).isNull();
            assertThat(student.getEmail()).isNotNull();
        });
    }        

What about MongoTemplate?

If you prefer to use MongoTemplate, it also works with Oracle Database — We can inject the MongoTemplate bean into our test and create another test case around it:

    @Autowired
    MongoTemplate mongoTemplate;

    @Test
    void mongoTemplateOperations() {
        // You may also use MongoTemplate to work with documents in Oracle Database.
        mongoTemplate.save(aliceSmith);
        mongoTemplate.save(johnDoe);

        assertThat(mongoTemplate.findAll(Student.class)).hasSize(2);
    }        

Let’s run the full test suite for MongoRepository and MongoTemplate

Using your pre-configured database instance, set the following environment variables:

  • DB_USERNAME (the database username you'll use to connect)
  • DB_PASSWORD (the database password you'll use to connect)
  • DB_URI (the URI of your database instance, e.g., my-db.adb.my-region.oraclecloudapps.com)

You can run the test using Maven from the root of the spring-data-mongodb-oracle-api module:

export DB_USERNAME=my-db-username
export DB_PASSWORd=my-db-password
export DB_URI=my-database-hostname
mvn test        

You should see output similar to the following. I recommend reading the test class to get an idea of what it’s doing. Note that no Oracle-specific APIs are being invoked by the client!

[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.715 s -- in com.example.mongodb.OracleMongoDBTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  7.045 s
[INFO] Finished at: 2025-04-02T11:00:10-07:00
[INFO] ------------------------------------------------------------------------        

Questions? Leave a comment or drop me line on LinkedIn!

Mohammed 모하마드

Java Developer: Spring Boot | Penetration Testing | AI Enthusiast

1mo

🔥

Like
Reply
Jeff Smith

Product Manager | Databases | Blogger | Software Development | Cloud | Social | Community Management | Product Marketing

1mo

Mongo APIs, plus SQL AND no-code REST access to your data sounds like a win to me (ORDS!) 

To view or add a comment, sign in

More articles by Anders Swanson

Insights from the community

Others also viewed

Explore topics