MongoDB is a popular NoSQL database and is a document-based one too. It is written using the popular and powerful C++ language, which makes it a document-oriented database. Queries are also document-based, and it also provides indexing using JSON style to store and retrieve data. MongoDB works on the concept of collection and documentation.
Let's look at few terminology differences between MySQL and MongoDB:
MySQL |
MongoDB |
---|---|
Table |
Collection |
Row |
Document |
Column |
Field |
Joins |
Embedded documents linking |
In MongoDB, a collection is a set or a group of documents. It is the same as RDBMS tables.
In this chapter, we shall start by setting up a MongoDB NoSQL database and will integrate a spring application with MongoDB to perform CRUD operations. The first example demonstrates updating single document values. The second example considers an order use case where it requires two document references to be stored in the collection. It demonstrates the flexibility in referencing different documents of MongoDB using objectId
references.
We need to go for a NoSQL database only if the applications have heavy write operations. MongoDB also suits the cloud environment very well, where we can take copies of databases easily.
In the next section, we shall see how we can get started with MongoDB, beginning with installing it, using the Spring Framework, and integrating MongoDB. To get started, we shall show basic Create, Retrieve, Update, and Delete (CRUD) operations with various use cases.
In this section we shall install MongoDB and create a database:
Download the MongoDB database at http://www.mongodb.org/downloads.
Configure the data folder by executing the following command in the
bin
folder:>mongod.exe -dbpath e:\mongodata\db
Start
mongod.exe
in another Command Prompt.Execute the following command:
>show databaseExecute
The
>show dbs
command also works fine with MongoDB.Execute the following command to create a new database, namely
eshopdb
.>use new-eshopdb
Executing
> show dbs
will still show thateshopdb
hasn't been created yet; this is because it doesn't contain any collections. Let's add some collections in the next step, once a collection is added.Execute the following snippet in the Command Prompt. The following snippets will insert sample documents into the collection:
db.eshopdb.insert({cust_id:1,name:"kishore",address:"jayangar"}) db.eshopdb.insert({cust_id:2,name:"bapi",address:"HAL Layout"}) db.eshopdb.insert({cust_id:3,name:"srini",address:"abbigere street"}) db.eshopdb.insert({cust_id:4,name:"sangamesha",address: "Kattarigupee layout"})
It's always easy to create a batch file to start MongoDB, and it's best to create a script file to start Mongo. This way, we won't have an error with the configuration. This would also save us a lot of time.
Create a
mongodbstart.bat
file.Edit the file and type in the following command and save it:
cd E:\MONGODB\mongo\bin mongod -dbpath e:\mongodata\db
The next time you want to start MongoDB, just click on the batch file.
Let us look at the Order use case to implement a simple CRUD operation using Spring and MongoDB. We are performing CRUD operations on Product, Customer, and Order documents. The scenario is this: a customer selects a product and places an order.
Following is the Order use case. The actor is the application user and will have the following options:
CRUD operation on Product Document
CRUD operation on Customer Document
CRUD operation on Order by selecting Product and Customer
Saving the Product Document Object ID and Customer Document Object ID in Order Document
We need to create a simple web application project using Maven.
Execute the following command in your Maven command prompt:
mvn archetype:generate -DgroupId=com.packtpub.spring -DartifactId=spring-mongo -DarchetypeArtifactId=maven-archetype-webapp
Create a simple Maven project with a web application archetype. Add the latest
4.0.2.RELEASE
spring dependency.The following is an extract from the
pom.xml
file. These are the mandatory dependencies to be added to thepom.xml
file.<!-- Spring dependencies --> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>2.9.1</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>1.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>1.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</}</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.0.2.RELEASE </version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.0.2.RELEASE </version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.0.2.RELEASE </version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.0.2.RELEASE </version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.0.2.RELEASE </version> <scope>runtime</scope> </dependency>
The following table contains the classes used to develop a simple CRUD application. The request flows from controller to model and back. The Repository classes are marked with the @Repository
annotation and connect to MongoDB using the mongoTemplate
class.
Controller |
Model |
JSP |
Bean |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
The following are the steps are for the implementation of the Spring4MongoDB_Chapter1
application:
Create a web-based Maven project with the name
Spring4MongoDB_Chapter1
.Import the project into Eclipse for the implementation. I have used Eclipse Juno.
We need to create the controller to map the requests.
The controller request is mapped to the GET
and POST
methods, as shown in the following table:
Request |
Request Method |
Model Attributes |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Following is the implementation of ProductController.java
. We have used the @Controller
annotation to indicate that the ProductController.java
class is a controller class. The @Autowired
annotation ties the ProductRepository
class with the ProductController.java
file.
The property
productList
is a list of type Product
that holds the products that are to be displayed on screen. The @PostConstruct
annotation will call the method decorated by it. Once the constructor of the class is called and all properties are set, and before any business methods are called, it's worthy to note as it's only called once.
@Controller public class ProductController { @Autowired private ProductRepository respository; private List <Product>productList; public ProductController() { super(); } @PostConstruct public void init(){ this.productList=respository.getAllObjects(); } //to get the list of products @RequestMapping(value="/product", method = RequestMethod.GET) public String getaddproduct(Model model) { model.addAttribute("productList", productList); model.addAttribute("productAttribute", new Product()); return "product"; } //to save the product @RequestMapping(value="/product/save", method = RequestMethod.POST) public String addproduct(@ModelAttribute Product prod,Model model) { if(StringUtils.hasText(prod.getProdid())) { respository.updateObject(prod); } else { respository.saveObject(prod); } this.productList=respository.getAllObjects(); model.addAttribute("productList", productList); return "product"; } //to update the edited product @RequestMapping(value="/product/update", method = RequestMethod.POST) public String updatecustomer(@ModelAttribute Product prod,Model model) { respository.updateObject(prod); this.productList=respository.getAllObjects(); model.addAttribute("productList", productList); return "product"; } //to edit a product based on ID @RequestMapping(value = "/product/geteditproduct", method = RequestMethod.GET) public String geteditproduct( @RequestParam(value = "prodid", required = true) String prodid, Model model) { model.addAttribute("productList", productList); model.addAttribute("productAttribute", respository.getObject(prodid)); return "editproduct"; } //to delete a product based on ID @RequestMapping(value="/product/deleteproduct", method = RequestMethod.GET) public String deleteproduct( @RequestParam(value = "prodid", required = true) String prodid,Model model) { respository.deleteObject(prodid); this.productList=respository.getAllObjects(); model.addAttribute("productList", this.productList); return "product"; } //to get all the products @RequestMapping(value = "/product/getallproducts", method = RequestMethod.GET) public String getallproducts(Model model) { this.productList=respository.getAllObjects(); model.addAttribute("productList", this.productList); return "allproducts"; } }
The Product.java
file has an @Document
annotation and an @ID
annotation, which is identified as a MongoDB collection that maps the Product
entity to product collection in MongoDB.
@Document public class Product { /*Bean class product with getter and setters*/ @Id private String prodid; private Double price; private String name; public Product() { super(); } public String getProdid() { return prodid; } public void setProdid(String prod_id) { this.prodid = prod_id; } public Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
The ProducRepository.java
file has @Repository
annotation. This is the persistence layer, and tells spring that this class performs operations on the database. The connection to Mongo is set up in Mongo template.
ProductRepository.java
@Repository public class ProductRepository { @Autowired MongoTemplate mongoTemplate; public void setMongoTemplate(MongoTemplate mongoTemplate) { this.mongoTemplate = mongoTemplate; } public List<Product> getAllObjects() { return mongoTemplate.findAll(Product.class); } /** * Saves a {@link Product}. */ public void saveObject(Product Product) { Product.setProdid(UUID.randomUUID().toString()); mongoTemplate.insert(Product); } /** * Gets a {@link Product} for a particular id. */ public Product getObject(String id) { return mongoTemplate.findOne(new Query(Criteria.where("_id").is(id)), Product.class); } /** * Updates a {@link Product} name for a particular id. */ public void updateObject(Product object) { Query query = new Query(); query.addCriteria(Criteria.where("_id").is(object.getProdid())); Product prod_tempObj = mongoTemplate.findOne(query, Product.class); System.out.println("cust_tempObj - " + prod_tempObj); //modify and update with save() prod_tempObj.setName(object.getName()); prod_tempObj.setPrice(object.getPrice()); mongoTemplate.save(prod_tempObj); } /** * Delete a {@link Product} for a particular id. */ public void deleteObject(String id) { mongoTemplate.remove(new Query(Criteria.where("_id").is(id)),Product.class); } /** * Create a {@link Product} collection if the collection does not already * exists */ public void createCollection() { if (!mongoTemplate.collectionExists(Product.class)) { mongoTemplate.createCollection(Product.class); } } /** * Drops the {@link Product} collection if the collection does already exists */ public void dropCollection() { if (mongoTemplate.collectionExists(Product.class)) { mongoTemplate.dropCollection(Product.class); } } }
The .jsp
file displays the products available and allows the user to perform CRUD operations on the
Product
bean. The following screenshot is the output of editing product information using the product ObjectId
stored in MongoDB.

Product.jsp file
This file serves as a view layer to the user. This has the product creation form and includes a file that lists all the products stored in MongoDB.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Register Product</title> </head> <body> <h1>Register Product</h1> <ul> <li><a href="/Spring4MongoDB_Chapter1/customer">Customer</a> </li> <li>r<a href="/Spring4MongoDB_Chapter1/order">Product</a> </li></ul> <form method="post" action="/Spring4MongoDB_Chapter1/product/save"> <table> <tr> <td> Name:</td> <td><input type=text name="name"/></td> </tr> <tr> <td>Price</td> <td><input type=text name="price"/></td> </tr> </table> <input type="hidden" name="prod_id" > <input type="submit" value="Save" /> </form> <%@ include file="allproducts.jsp" %> </body> </html>
If all goes well, you should see the following screen, where you can play around with products. The following screenshot is the output of the Register Product and list Product functionality using Spring and MongoDB.

The following dispatcher-servlet.xml
file shows the configuration for component scan and MongoDB template. It also shows the MongoDB database name configuration.
dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mongo="http://www.springframework.org/schema/data/mongo" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <context:component-scan base-package="com.packt" /> <!-- Factory bean that creates the Mongo instance --> <bean id="mongo" class="org.springframework.data.mongodb.core.MongoFactoryBean"> <property name="host" value="localhost" /> </bean> <mongo:mongo host="127.0.0.1" port="27017" /> <mongo:db-factory dbname="eshopdb" /> <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" /> </bean> <!-- Use this post processor to translate any MongoExceptions thrown in @Repository annotated classes --> <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" /> <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/myviews/" p:suffix=".jsp" /> </beans>
You can see that the mongoDbFactory
bean has been configured with MongoDB database details. You will also observe that mongoTemplate
has also been configured. The property of the mongoTemplate
bean is mongoDbFactory
bean, and so when the template is called the connection gets established.
Just run the following commands in the MongoDB database in order to test the Order use case:
Let's consider a complex scenario for this section. In the use case that we have considered, the Order use case has customer and product objects in the class. When a user places an order, the user will select a product and customer.
Our aim here is to store the customer
and product
classes directly in the Order
collection in MongoDB. Let's first implement the OrderBean
class with getter and setters.
Order.java
package com.packt.bean; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; @Document public class Order { private String order_id; private Customer customer; private Product product; private String date; private String order_status; private int quantity; public Order() { super(); // TODO Auto-generated constructor stub } @Id public String getOrder_id() { return order_id; } public void setOrder_id(String order_id) { this.order_id = order_id; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public int getQuantity() { return quantity; } public void setQuantity(int quantity) { this.quantity = quantity; } public String getOrder_status() { return order_status; } public void setOrder_status(String order_status) { this.order_status = order_status; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } public Product getProduct() { return product; } public void setProduct(Product product) { this.product = product; } }
The next step would be to define the methods in the OrderRepository.java
file.

Below are the code snippets of the update
and save
methods in the repository
class.
We see that the update Order
method accepts the Order
object. We used the addCriteria()
method to get a particular order based on the object ID. The Order
object retrieved is stored in the temp
object. The values are then set to the temp
object based on the object that is passed to the method. Then, the mongoTemplate.save(Object)
method is called to update the saved object.
public void updateObject(Order order) { Query query = new Query(); query.addCriteria(Criteria.where("_id").is(order.getOrder_id())); Order order_tempObj = mongoTemplate.findOne(query, Order.class); order_tempObj.setCustomer(order.getCustomer()); order_tempObj.setProduct(order.getProduct()); order_tempObj.setQuantity(order.getQuantity()); mongoTemplate.save(order_tempObj); }
The saveObject
method only accepts the Order
object and sets the ID to the Order
object before saving it.
We have seen how to perform an update and an insert. The following method is invoked to save the Order details. This shows that mongoTemplate
has the methods insert()
and save()
.
public void saveObject(Order Order) { Order.setOrder_id(UUID.randomUUID().toString()); mongoTemplate.insert(Order); }
The controller
class has the customer repository and product repository references as per the use case. The application user needs to select the customer and product to place an order.
The initial Skelton of OrderController
is shown here:
@Controller public class OrderController { @Autowired private OrderRepository respository; @Autowired private CustomerRepository customerRespository; @Autowired private ProductRepository productRespository; private List<Order> orderList; private List<Customer> customerList; private List<Product> productList; public OrderController() { super(); } }
The
controller
class is to handle the
Order
requests. The @ModelAttribute
annotation is added to the method. The product list and customer list is always available as a model attribute to the controller. The following is the code snippet of the OrderController
class:
@ModelAttribute("orderList") public List<Order> populateOrderList() { this.orderList = respository.getAllObjects(); return this.orderList; } @ModelAttribute("productList") public List<Product> populateProductList() { this.productList = productRespository.getAllObjects(); return this.productList; } @ModelAttribute("customerList") public List<Customer> populateCstomerList() { this.customerList = customerRespository.getAllObjects(); return this.customerList; }
The methods are mapped to a particular request, @ModelAttribute("Order")
, to make the order object easily accessible at the JSP level. You can observe that using @ModelAttribute
at the method level; this will minimize adding @ModelAttribute
to the method.
@RequestMapping(value = "/order", method = RequestMethod.GET) // request show add order page public String addOrder(@ModelAttribute("Order") Order order,Map<String, Object> model) { model.put("customerList", customerList); model.put("productList", productList); return "order"; } @RequestMapping(value = "/order/save", method = RequestMethod.POST) // request to insert the record public String addorder(@ModelAttribute("Order") Order order,Map<String, Object> model) { order.setCustomer(customerRespository.getObject(order.getCustomer().getCust_id())); order.setProduct(product_respository.getObject(order.getProduct().getProdid())); respository.saveObject(order); model.put("customerList", customerList); model.put("productList", productList); return "order"; } @RequestMapping(value = "/orde`r/update", method = RequestMethod.POST) public String updatecustomer(@ModelAttribute("Order") Order order, Map<String, Object> model) { order.setCustomer(customerRespository.getObject(order.getCustomer().getCust_id())); order.setProduct(product_respository.getObject(order.getProduct().getProdid())); respository.updateObject(order); model.put("customerList", customerList); model.put("productList", productList); return "order"; } @RequestMapping(value = "/order/geteditorder", method = RequestMethod.GET) public String editOrder(@RequestParam(value = "order_id", required = true) String order_id, @ModelAttribute("Order") Order order,Map<String, Object> model) { model.put("customerList", customerList); model.put("productList", productList); model.put("Order",respository.getObject(order_id)); return "editorder"; } @RequestMapping(value = "/order/deleteorder", method = RequestMethod.GET) public String deleteorder(@RequestParam(value = "order_id", required = true) String order_id, @ModelAttribute("Order") Order order,Map<String, Object> model) { respository.deleteObject(order_id); model.put("customerList", customerList); model.put("productList", productList); return "order"; } }
The Order.jsp
file demonstrates the use of @ModelAttribute
, which gets mapped to the Model Order defined in the controller class. The setter methods set the values to the objects, which minimizes the coding. This showcases a feature in spring, which simplifies the coding process.
Orders.jsp
<h1>Orders </h1> <ul> <li><a href="/Spring4MongoDB_Chapter1/customer">Customer</a> </li> <li>r<a href="/Spring4MongoDB_Chapter1/product">Product</a> </li></ul> <form:form action="/Spring4MongoDB_Chapter1/order/save" modelAttribute="Order"> <table> <tr> <td>Add your Order:</td> <td><form:input path="quantity" size="3"/></td> </tr> <tr> <td>Select Product:</td> <td> <form:select path="product.prodid"> <form:option value="" label="--Please Select"/> <form:options items="${productList}" itemValue="prodid" itemLabel="name"/> </form:select> </td> </tr> <tr> <td>Select Customer:</td> <td> <form:select path="customer.cust_id"> <form:option value="" label="--Please Select"/> <form:options items="${customerList}" itemValue="cust_id" itemLabel="name"/> </form:select> </td> </tr> <tr> <td colspan="2" align="center"> <input type="submit" value="Submit" /> </td> </tr> </table> </form:form> <%@ include file="allorders.jsp" %> </body> </html>
The allorders.jsp
file displays the list of orders with an option to edit. Use of MongoDB has made displaying the orderList
simpler.
Allorders.jsp
<h1> E-shop Orders</h1> <table style="border: 1px solid; width: 500px; text-align:center"> <thead style="background:#fffcc"> <tr> <th>Order Id</th> <th>Customer Name</th> <th>Customer Address</th> <th>Product Address</th> <th>Product Price</th> <th>Product Quantity</th> <th colspan="2"></th> </tr> </thead> <tbody> <c:forEach items="${orderList}" var="order"> <c:url var="editUrl" value="/order/geteditorder?order_id=${order.order_id}" /> <c:url var="deleteUrl" value="/order/deleteorder?order_id=${order.order_id}" /> <c:url var="addUrl" value="/order/" /> <tr> <td><c:out value="${order.order_id}" /></td> <td><c:out value="${order.customer.name}" /></td> <td><c:out value="${order.customer.address}" /></td> <td><c:out value="${order.product.name}" /></td> <td><c:out value="${order.product.price}" /></td> <td><c:out value="${order.quantity}" /></td> <td><a href="${editUrl}">Edit</a></td> <td><a href="${deleteUrl}">Delete</a></td> <td><a href="${addUrl}">Add</a></td> </tr> </c:forEach> </tbody>
The following is a screenshot of the page to add your order:

The following is a screenshot of the page to edit your order:

In this chapter, we learned how to install MongoDB and create a database and collections. In MongoDB, we have used the latest version of spring that was available during the writing of this chapter. We also learned how to integrate Spring MVC with MongoDB. We have built a CRUD operation. We have also seen the usage of annotations such as @Repository
, @Document
, and @Controller
. In the next chapter, let us see how we can integrate spring message brokers using jms
templates.