Spring Data Mongodb
Spring Data for MongoDB is an Object-Document Mapper library. To use Spring Data for MongoDB, add the dependencies for Spring Data and the MongoDB Driver.
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.4.1</version>
</dependency>
</dependencies>
Define the POJO class for the data model:
package com.pockettheories;
public class Person {
public String id;
public String firstName;
public String lastName;
public Person(String firstName, String lastName) {this.firstName=firstName; this.lastName=lastName;}
}
Then, in the Main class, use the MongoTemplate class, which implements the interface MongoOperations. The API of the MongoOperations class is similar to the MongoClient class in name, but it uses POJO objects instead of the Document objects as parameters:
package com.pockettheories;
import static org.springframework.data.mongodb.core.query.Criteria.where;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import com.mongodb.client.MongoClients;
import java.util.List;
public class Main {
public static void main(String args[]) {
MongoOperations mongoOps = new MongoTemplate(MongoClients.create(), "database");
//Insert a document
mongoOps.insert(new Person("Nitin", "Reddy"));
//Fetch a document with query criteria
Person obj = mongoOps.findOne(new Query(where("firstName").is("Nitin")), Person.class);
//Fetch all documents from the collection
List<Person> lstResults = mongoOps.findAll(Person.class);
//Update a document
obj.lastName = "Katkam";
mongoOps.save(obj);
//Delete a document
mongoOps.remove(obj).getDeletedCount();
System.out.println("Done!");
}
}
Execute the application with
mvn compile
mvn exec:java -Dexec.mainClass=com.example.MainClass
Spring Data MongoDB can embed related data within a document by serializing an entire document tree. For example:
//Publisher.java
package com.pockettheories;
public class Publisher {
public String name;
}
//Book.java
package com.pockettheories;
public class Book {
public String id;
public String title;
public Publisher publisher;
}
//Main.java
Book book = new Book();
book.title = "Harry Potter";
book.publisher = new Publisher();
book.publisher.name = "Bloomsbury Publishing";
mongoOps.insert(book);
Embedding can also be performed for a list of objects:
//Product.java
package com.pockettheories;
public class Product {
public String name;
}
//Category.java
package com.pockettheories;
import java.util.List;
public class Category {
public List<Product> products;
public String name;
}
//Main.java
Category cat = new Category();
Product product1 = new Product();
product1.name = "NaCL";
Product product2 = new Product();
product2.name = "H2O";
cat.name = "Chemicals";
cat.products = new ArrayList<Product>();
cat.products.add(product1);
cat.products.add(product2);
mongoOps.insert(cat);
//Main.java - Update without fetching the category
Product product3 = new Product();
product3.name = "C6H12O6";
mongoOps.update(Category.class)
.matching(where("name").is(cat.name))
.apply(new Update().push("products", product3))
.first();
Category cat_ = mongoOps.findOne(new Query(where("name").is(cat.name)), Category.class);
System.out.println("Category has " + cat_.products.size() + " products");
Instead of embedding within a document, the related data can be linked with DBRef.
//Supplier.java
package com.pockettheories;
public class Supplier {
public String id;
public String name;
}
//Part.java
package com.pockettheories;
import org.springframework.data.mongodb.core.mapping.DBRef;
public class Part {
public String id;
public String name;
@DBRef
public Supplier supplier;
}
//Main.java
Part part = new Part();
part.name = "Screwdriver";
part.supplier = new Supplier();
part.supplier.name = "Stanley";
mongoOps.insert(part.supplier);
mongoOps.insert(part);
In the above example, the Spring Data MongoDB library stores the DBRef from the part to the supplier. The relationship can also be ‘manually’ managed by storing the ID, instead of storing the object reference on the referencing class:
//Owner.java
package com.pockettheories;
import java.util.List;
import org.springframework.data.annotation.*;
import org.springframework.data.mongodb.core.mapping.*;
public class Owner {
public String id;
//@ReadOnlyProperty
@DocumentReference(lookup="{'owner':?#{#self._id} }")
List<Pet> pets;
public String name;
}
//Pet.java
package com.pockettheories;
public class Pet {
public String id;
public String owner;
public String name;
}
//Main.java
int min = 0;
int max = 9999;
int randomNum = ThreadLocalRandom.current().nextInt(min, max + 1);
Pet pet = new Pet();
Owner owner = new Owner();
owner.id = "NI_" + (new Integer(randomNum)).toString();
owner.name = "Nitin";
pet.owner = owner.id;
pet.name = "Thinkpad";
mongoOps.insert(pet);
mongoOps.insert(owner);
Owner owner_ = mongoOps.findOne(new Query(where("id").is(owner.id)), Owner.class);
System.out.println("Owner has " + owner_.pets.size() + " pets");
Spring Data can also execute MongoDB aggregation queries:
package com.pockettheories;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import java.util.Date;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.group;
public class NewMain {
public static void main(String args[]) {
MongoClient client = MongoClients.create("mongodb://localhost");
MongoOperations mongoOps = new MongoTemplate(client, "test");
class Plant {
public String name;
public String mytype;
public java.util.Date recordedAt;
}
class PlantSummary {
public String _id;
public int count;
public String toString() { return _id + ": " + Integer.toString(count); }
}
//
// Remove old data
//
mongoOps.dropCollection("plant");
//
// Insert sample data
//
Plant p1 = new Plant();
p1.name = "Hibiscus";
p1.mytype = "Flower";
p1.recordedAt = new Date();
Plant p2 = new Plant();
p2.name = "Mango";
p2.mytype = "Fruit";
p2.recordedAt = new Date();
Plant p3 = new Plant();
p3.name = "Rose";
p3.mytype = "Flower";
p3.recordedAt = new Date();
mongoOps.insert(p1);
mongoOps.insert(p2);
mongoOps.insert(p3);
//
// Build the aggregation pipeline stages
//
MatchOperation matchStage = Aggregation.match(new Criteria("name").is("Hibiscus"));
SetOperation setStage = SetOperation.set("monthYear").toValueOf(
DateOperators.dateOf("recordedAt").toString("%Y-%m")
) ;
GroupOperation groupStage = group("monthYear").count().as("count");
// GroupOperation groupStage = group("mytype").count().as("count");
// GroupOperation groupStage = group("mytype").sum("noOfPetals").as("petalCount");
Aggregation agg1 = Aggregation.newAggregation(
matchStage
,
setStage
,
groupStage
);
AggregationResults<PlantSummary> results = mongoOps.aggregate(agg1, "plant", PlantSummary.class);
System.out.println(agg1.toString());
results.forEach(s -> System.out.println(s));
}
}