Section 5: Programming

β˜• MongoDB with Java

Complete tutorial on using MongoDB with Java - CRUD operations, Spring Boot, and best practices

2 Approaches
CRUD Full Operations
Spring Boot Integration
Java 11+ Modern Java
βš™οΈ

Setup & Dependencies

Get started with MongoDB Java driver

Maven
Gradle

Maven Dependencies

pom.xml
<!-- MongoDB Java Driver (Sync) -->
<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongodb-driver-sync</artifactId>
    <version>4.11.1</version>
</dependency>

<!-- For Spring Boot -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

Gradle Dependencies

build.gradle
// MongoDB Java Driver (Sync)
implementation 'org.mongodb:mongodb-driver-sync:4.11.1'

// For Spring Boot
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
πŸ”Œ

Connecting to MongoDB

Establish database connection

Basic Connection

MongoDBConnection.java
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoCollection;
import org.bson.Document;

public class MongoDBConnection {
    public static void main(String[] args) {
        // Connection string
        // Local: "mongodb://localhost:27017"
        // Atlas: "mongodb+srv://user:pass@cluster0.mongodb.net/"
        String uri = "mongodb://localhost:27017";

        // Create client (try-with-resources)
        try (MongoClient mongoClient = MongoClients.create(uri)) {
            
            // Get database
            MongoDatabase database = mongoClient.getDatabase("myapp");
            
            // Get collection
            MongoCollection<Document> collection = 
                database.getCollection("users");
            
            System.out.println("Connected to MongoDB!");
            System.out.println("Database: " + database.getName());
            System.out.println("Collection: " + collection.getNamespace());
        }
    }
}
βœ… Connection Established!

The try-with-resources automatically closes the connection.

User Model (POJO)

User.java
import org.bson.types.ObjectId;
import java.util.Date;

public class User {
    private ObjectId id;
    private String name;
    private String email;
    private int age;
    private boolean active;
    private Date createdAt;

    // Constructors
    public User() {}

    public User(String name, String email, int age, boolean active) {
        this.name = name;
        this.email = email;
        this.age = age;
        this.active = active;
        this.createdAt = new Date();
    }

    // Getters and Setters
    public ObjectId getId() { return id; }
    public void setId(ObjectId id) { this.id = id; }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }

    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }

    public boolean isActive() { return active; }
    public void setActive(boolean active) { this.active = active; }

    public Date getCreatedAt() { return createdAt; }
    public void setCreatedAt(Date createdAt) { this.createdAt = createdAt; }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", age=" + age +
                ", active=" + active +
                ", createdAt=" + createdAt +
                '}';
    }
}
πŸ’Ύ

CRUD Operations

Create, Read, Update, Delete

Insert Documents

Insert Operations
import com.mongodb.client.result.InsertOneResult;
import com.mongodb.client.result.InsertManyResult;
import java.util.Arrays;
import java.util.Date;

// Insert One
public static void insertOne(MongoCollection<Document> collection) {
    Document user = new Document("name", "Alice Johnson")
            .append("email", "alice@example.com")
            .append("age", 28)
            .append("active", true)
            .append("createdAt", new Date());

    InsertOneResult result = collection.insertOne(user);
    System.out.println("Inserted ID: " + result.getInsertedId());
}

// Insert Many
public static void insertMany(MongoCollection<Document> collection) {
    List<Document> users = Arrays.asList(
        new Document("name", "Bob Smith")
            .append("email", "bob@example.com")
            .append("age", 35)
            .append("active", true),
        new Document("name", "Carol White")
            .append("email", "carol@example.com")
            .append("age", 42)
            .append("active", false)
    );

    InsertManyResult result = collection.insertMany(users);
    System.out.println("Inserted " + result.getInsertedIds().size() + " documents");
}

Find Documents

Find Operations
import com.mongodb.client.FindIterable;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Sorts;

// Find One
public static void findOne(MongoCollection<Document> collection) {
    Document user = collection.find(Filters.eq("email", "alice@example.com"))
                              .first();
    
    if (user != null) {
        System.out.println("Found user: " + user.toJson());
    } else {
        System.out.println("No user found");
    }
}

// Find Many
public static void findMany(MongoCollection<Document> collection) {
    // Find active users, sorted by name, limit 10
    FindIterable<Document> users = collection
        .find(Filters.eq("active", true))
        .sort(Sorts.ascending("name"))
        .limit(10);

    for (Document user : users) {
        System.out.println(user.getString("name") + 
                           " - " + user.getString("email"));
    }
}

// Complex Query
public static void complexQuery(MongoCollection<Document> collection) {
    // Age between 25 and 40, and active
    FindIterable<Document> users = collection.find(
        Filters.and(
            Filters.gte("age", 25),
            Filters.lte("age", 40),
            Filters.eq("active", true)
        )
    );

    System.out.println("Users between 25-40:");
    users.forEach(user -> System.out.println(user.toJson()));
}
πŸ’‘ Filter Helpers
  • Filters.eq() - Equal to
  • Filters.gt/gte() - Greater than (or equal)
  • Filters.lt/lte() - Less than (or equal)
  • Filters.in() - Matches any value in array
  • Filters.and/or() - Logical operators
  • Filters.regex() - Regular expression

Update Documents

Update Operations
import com.mongodb.client.result.UpdateResult;
import com.mongodb.client.model.Updates;

// Update One
public static void updateOne(MongoCollection<Document> collection) {
    UpdateResult result = collection.updateOne(
        Filters.eq("email", "alice@example.com"),
        Updates.combine(
            Updates.set("age", 29),
            Updates.set("updatedAt", new Date())
        )
    );

    System.out.println("Matched: " + result.getMatchedCount());
    System.out.println("Modified: " + result.getModifiedCount());
}

// Update Many
public static void updateMany(MongoCollection<Document> collection) {
    // Activate all inactive users
    UpdateResult result = collection.updateMany(
        Filters.eq("active", false),
        Updates.set("active", true)
    );

    System.out.println("Updated " + result.getModifiedCount() + " documents");
}

// Increment Value
public static void incrementAge(MongoCollection<Document> collection) {
    collection.updateOne(
        Filters.eq("email", "alice@example.com"),
        Updates.inc("age", 1) // Increment age by 1
    );
}

Delete Documents

Delete Operations
import com.mongodb.client.result.DeleteResult;

// Delete One
public static void deleteOne(MongoCollection<Document> collection) {
    DeleteResult result = collection.deleteOne(
        Filters.eq("email", "alice@example.com")
    );

    System.out.println("Deleted " + result.getDeletedCount() + " document");
}

// Delete Many
public static void deleteMany(MongoCollection<Document> collection) {
    // Delete users older than 50
    DeleteResult result = collection.deleteMany(
        Filters.gt("age", 50)
    );

    System.out.println("Deleted " + result.getDeletedCount() + " documents");
}
πŸƒ

Spring Boot Integration

Modern approach with Spring Data MongoDB

Configuration

application.properties
# Local MongoDB
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=myapp

# OR Atlas connection string
# spring.data.mongodb.uri=mongodb+srv://user:pass@cluster0.mongodb.net/myapp

Entity Model

User.java (Entity)
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import java.util.Date;

@Document(collection = "users")
public class User {
    
    @Id
    private String id;
    
    private String name;
    private String email;
    private int age;
    private boolean active;
    private Date createdAt;

    // Constructors
    public User() {}

    public User(String name, String email, int age, boolean active) {
        this.name = name;
        this.email = email;
        this.age = age;
        this.active = active;
        this.createdAt = new Date();
    }

    // Getters and Setters...
}

Repository Interface

UserRepository.java
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
import java.util.List;

public interface UserRepository extends MongoRepository<User, String> {
    
    // Derived query methods
    User findByEmail(String email);
    List<User> findByActive(boolean active);
    List<User> findByAgeBetween(int minAge, int maxAge);
    
    // Custom query
    @Query("{ 'age': { $gte: ?0, $lte: ?1 }, 'active': true }")
    List<User> findActiveUsersInAgeRange(int minAge, int maxAge);
    
    // Count
    long countByActive(boolean active);
}

Service Layer

UserService.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;

@Service
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    // Create
    public User createUser(User user) {
        return userRepository.save(user);
    }
    
    // Read
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }
    
    public Optional<User> getUserById(String id) {
        return userRepository.findById(id);
    }
    
    public User getUserByEmail(String email) {
        return userRepository.findByEmail(email);
    }
    
    public List<User> getActiveUsers() {
        return userRepository.findByActive(true);
    }
    
    // Update
    public User updateUser(String id, User updatedUser) {
        return userRepository.findById(id)
            .map(user -> {
                user.setName(updatedUser.getName());
                user.setEmail(updatedUser.getEmail());
                user.setAge(updatedUser.getAge());
                user.setActive(updatedUser.isActive());
                return userRepository.save(user);
            })
            .orElseThrow(() -> new RuntimeException("User not found"));
    }
    
    // Delete
    public void deleteUser(String id) {
        userRepository.deleteById(id);
    }
}
βœ… Spring Boot Benefits
  • Automatic repository implementation
  • Derived query methods from method names
  • Transaction support
  • Pagination and sorting
  • Integration with Spring ecosystem
πŸ“Š

Aggregation Pipeline

Complex data operations

Basic Aggregation

Aggregation Example
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.model.Aggregates;
import com.mongodb.client.model.Accumulators;
import java.util.Arrays;

public static void aggregation(MongoCollection<Document> collection) {
    // Pipeline: Match, Group, Sort
    AggregateIterable<Document> result = collection.aggregate(Arrays.asList(
        // Match: age >= 25
        Aggregates.match(Filters.gte("age", 25)),
        
        // Group by active status
        Aggregates.group(
            "$active",
            Accumulators.sum("count", 1),
            Accumulators.avg("avgAge", "$age")
        ),
        
        // Sort by count descending
        Aggregates.sort(Sorts.descending("count"))
    ));

    // Print results
    for (Document doc : result) {
        System.out.println(doc.toJson());
    }
}
⭐

Best Practices

Production-ready code

Connection Management

⚠️ Important Tips
  • Reuse Client: Create one MongoClient, reuse across application
  • Use Try-With-Resources: Automatic resource management
  • Connection Pool: Driver manages pooling automatically
  • Spring Boot: Let Spring manage the connection
  • Error Handling: Always handle exceptions properly
  • Indexes: Create indexes for frequently queried fields

Production Example

MongoDBConfig.java
import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import java.util.concurrent.TimeUnit;

public class MongoDBConfig {
    
    private static MongoClient mongoClient;
    
    public static MongoClient getClient() {
        if (mongoClient == null) {
            ConnectionString connectionString = 
                new ConnectionString("mongodb://localhost:27017");
            
            MongoClientSettings settings = MongoClientSettings.builder()
                .applyConnectionString(connectionString)
                .applyToConnectionPoolSettings(builder ->
                    builder.maxSize(100)
                           .minSize(10)
                           .maxWaitTime(2, TimeUnit.SECONDS)
                )
                .build();
            
            mongoClient = MongoClients.create(settings);
        }
        return mongoClient;
    }
    
    public static void close() {
        if (mongoClient != null) {
            mongoClient.close();
        }
    }
}
βœ… You're Ready!

You now have complete knowledge of MongoDB with Java. Build amazing applications!