Welcome to Spring Data MongoDB example. Spring Data MongoDB is one of the Spring projects for integrating Spring Framework with most widely used NoSQL database MongoDB.

Spring Data MongoDB

One of the key benefit of using Spring is that it provides integration with most of the major frameworks that are used in enterprise application. For example, Spring ORM Hibernate Integration.

We will use latest version of Spring Framework and Spring Data MongoDB for our example project. Our final Spring Data MongoDB example project will look like below image.

Spring-Data-MongoDB

Spring Data MongoDB can be used in a simple application too, it’s not required to use Spring framework with it. Let’s see this with a simple Spring MongoDB example. For that all you need to include below dependencies in pom.xml file, it will automatically include the compatible MongoDB java driver through maven transitive dependencies.


<dependency>
	<groupId>org.springframework.data</groupId>
	<artifactId>spring-data-mongodb</artifactId>
	<version>1.5.2.RELEASE</version>
</dependency>

Spring Data MongoDB Example – Model Bean

We will have a simple model bean with some variables to be stored in MongoDB database.

Person.java


package com.journaldev.spring.mongodb.model;
import org.springframework.data.annotation.Id;
public class Person {
	//id will be used for storing MongoDB _id
	@Id
	private String id;
	private String name;
	private String address;
	public Person(){}
	public Person(String i, String n, String a){
		this.id=i;
		this.name=n;
		this.address=a;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	@Override
	public String toString(){
		return id+"::"+name+"::"+address;
	}
}

It’s a simple java bean, however there are few important points that you should know.

  1. We know that every document in MongoDB is required to have a primary key with name _id, we can either provide it or MongoDB will generate it for us. We can use org.springframework.data.annotation.Id annotation with a model bean variable to map it to _id field.
  2. If the field name is “id” then we don’t need to use the @Id annotation, however it’s best practice to use it. In above class, we could have skipped @Id annotation.
  3. You should always have id field in the bean, otherwise it will not be mapped to any of the properties of the object and you will loose the primary key reference.

Now let’s see how we can easily use Spring Data MongoDB to perform CRUD operations on MongoDB database.

SpringDataMongoDBMain.java


package com.journaldev.spring.mongodb.main;
import java.net.UnknownHostException;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import com.journaldev.spring.mongodb.model.Person;
import com.mongodb.MongoClient;
public class SpringDataMongoDBMain {
	public static final String DB_NAME = "journaldev";
	public static final String PERSON_COLLECTION = "Person";
	public static final String MONGO_HOST = "localhost";
	public static final int MONGO_PORT = 27017;
	public static void main(String[] args) {
		try {
			MongoClient mongo = new MongoClient(
					MONGO_HOST, MONGO_PORT);
			MongoOperations mongoOps = new MongoTemplate(mongo, DB_NAME);
			Person p = new Person("113", "PankajKr", "Bangalore, India");
			mongoOps.insert(p, PERSON_COLLECTION);
			Person p1 = mongoOps.findOne(
					new Query(Criteria.where("name").is("PankajKr")),
					Person.class, PERSON_COLLECTION);
			System.out.println(p1);
			mongoOps.dropCollection(PERSON_COLLECTION);
			mongo.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
	}
}

Now when I run above Spring Data MongoDB example program, it generates following output.


02:02:14.785 [main] DEBUG o.s.d.m.c.i.MongoPersistentEntityIndexCreator - Analyzing class class com.journaldev.spring.mongodb.model.Person for index information.
02:02:14.794 [main] DEBUG o.s.data.mongodb.core.MongoTemplate - Inserting DBObject containing fields: [_class, _id, name, address] in collection: Person
02:02:14.798 [main] DEBUG o.s.data.mongodb.core.MongoDbUtils - Getting Mongo Database name=[journaldev]
02:02:14.824 [main] DEBUG o.s.data.mongodb.core.MongoTemplate - findOne using query: { "name" : "PankajKr"} fields: null for class: class com.journaldev.spring.mongodb.model.Person in collection: Person
02:02:14.826 [main] DEBUG o.s.data.mongodb.core.MongoDbUtils - Getting Mongo Database name=[journaldev]
02:02:14.826 [main] DEBUG o.s.data.mongodb.core.MongoTemplate - findOne using query: { "name" : "PankajKr"} in db.collection: journaldev.Person
113::PankajKr::Bangalore, India
02:02:14.833 [main] DEBUG o.s.data.mongodb.core.MongoDbUtils - Getting Mongo Database name=[journaldev]
02:02:14.835 [main] DEBUG o.s.data.mongodb.core.MongoTemplate - Dropped collection [journaldev.Person]

We can conclude following points for Spring Data MongoDB from our learning till now.

  1. Spring Data MongoDB provides wrapper over the MongoDB java driver, internally it’s using MongoDB java driver to perform database operations.
  2. MongoOperations declares a lot of methods for different operations and most of the time, they are sufficient for us. MongoTemplate is the implementation class and it requires Mongo or MongoClient (for newer MongoDB java driver versions) or MongoDbFactory to initialize it. We also need to provide the database name which will be used.
  3. If database is password protected, we can use org.springframework.data.authentication.UserCredentials to pass the authentication username and password details.
  4. org.springframework.data.mongodb.core.query.Query and org.springframework.data.mongodb.core.query.Criteria classes are used to define the query used to find particular record or records.
  5. The major benefit of Spring Data MongoDB is that we don’t need to worry about the conversion of java bean to Mongo DBObject and vice versa, as we saw in MongoDB Java Example.

Now let’s move forward to use Spring Data MongoDB in Spring environment. It’s very simple and mostly requires configuration related code that we can do through XML, annotations or through java config. However I will use XML based configuration for Spring Data MongoDB example.

Here is my final pom.xml with Spring Framework and Spring Data MongoDB dependencies.


<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.springframework.samples</groupId>
  <artifactId>SpringMongo</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <properties>
		<!-- Generic properties -->
		<java.version>1.6</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<!-- Spring -->
		<spring-framework.version>4.0.3.RELEASE</spring-framework.version>
		<spring-data-mongodb.version>1.5.2.RELEASE</spring-data-mongodb.version>
		<!-- Logging -->
		<logback.version>1.0.13</logback.version>
		<slf4j.version>1.7.5</slf4j.version>
	</properties>
	<dependencies>
		<!-- Spring and Transactions -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
		<dependency>
    		<groupId>org.springframework.data</groupId>
    		<artifactId>spring-data-mongodb</artifactId>
    		<version>${spring-data-mongodb.version}</version>
  		</dependency>
		<!-- Logging with SLF4J & LogBack -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${slf4j.version}</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>${logback.version}</version>
			<scope>runtime</scope>
		</dependency>
	</dependencies>
</project>

Spring Data MongoDB DAO Classes

We will use DAO pattern for exposing different operations that can be performed on Person object.

PersonDAO.java


package com.journaldev.spring.mongodb.dao;
import com.journaldev.spring.mongodb.model.Person;
public interface PersonDAO {
	public void create(Person p);
	public Person readById(String id);
	public void update(Person p);
	public int deleteById(String id);
}

Below is the MongoDB specific implementation class.

PersonDAOImpl.java


package com.journaldev.spring.mongodb.dao;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import com.journaldev.spring.mongodb.model.Person;
import com.mongodb.WriteResult;
public class PersonDAOImpl implements PersonDAO {
	private MongoOperations mongoOps;
	private static final String PERSON_COLLECTION = "Person";
	public PersonDAOImpl(MongoOperations mongoOps){
		this.mongoOps=mongoOps;
	}
	@Override
	public void create(Person p) {
		this.mongoOps.insert(p, PERSON_COLLECTION);
	}
	@Override
	public Person readById(String id) {
		Query query = new Query(Criteria.where("_id").is(id));
		return this.mongoOps.findOne(query, Person.class, PERSON_COLLECTION);
	}
	@Override
	public void update(Person p) {
		this.mongoOps.save(p, PERSON_COLLECTION);
	}
	@Override
	public int deleteById(String id) {
		Query query = new Query(Criteria.where("_id").is(id));
		WriteResult result = this.mongoOps.remove(query, Person.class, PERSON_COLLECTION);
		return result.getN();
	}
}

The code is pretty straight forward, so I won’t explain about them in detail.

Spring Data MongoDB Bean Configuration File

As always, the most important part of this application will be the spring bean configuration file. We will inject dependencies into different beans and define them.

Here is our final spring bean configuration file.

spring.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="https://www.springframework.org/schema/context"
	xmlns:mongo="https://www.springframework.org/schema/data/mongo"
	xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context-4.0.xsd
		https://www.springframework.org/schema/data/mongo https://www.springframework.org/schema/data/mongo/spring-mongo-1.5.xsd">
<mongo:mongo host="localhost" port="27017" id="mongo" />
<mongo:db-factory dbname="journaldev" mongo-ref="mongo" id="mongoDbFactory" />
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
	<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
</bean>
<bean id="personDAO" class="com.journaldev.spring.mongodb.dao.PersonDAOImpl">
	<constructor-arg name="mongoOps" ref="mongoTemplate"/>
</bean>
</beans>

The important configurations that should be present are – Spring Data MongoDB schema and Mongo instance for MongoDB connection. I have defined MongoDbFactory instance for my convenience, we could also define MongoTemplate bean like below,


<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
	<constructor-arg name="mongo" ref="mongo" />
	<constructor-arg name="databaseName" value="journaldev" />
</bean>

Spring Data MongoDB Test Program

Finally, let’s write a simple test program and run some CRUD operations on MongoDB database.

SpringMongoDBXMLMain.java


package com.journaldev.spring.mongodb.main;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.journaldev.spring.mongodb.dao.PersonDAO;
import com.journaldev.spring.mongodb.model.Person;
public class SpringMongoDBXMLMain {
	public static void main(String[] args) {
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
		PersonDAO personDAO = ctx.getBean("personDAO", PersonDAO.class);
		Person p = new Person(null, "PankajKr", "Bangalore, India");
		//create
		personDAO.create(p);
		System.out.println("Generated ID="+p.getId());
		//read
		Person p1 = personDAO.readById(p.getId());
		System.out.println("Retrieved Person="+p1);
		//update
		p1.setName("David");p1.setAddress("SFO, USA");
		personDAO.update(p1);
		Person temp = personDAO.readById(p1.getId());
		System.out.println("Retrieved Person after update="+temp);
		//delete
		int count = personDAO.deleteById(p1.getId());
		System.out.println("Number of records deleted="+count);
		ctx.close();
	}
}

Now when I run above application, it generates following output.


02:27:34.509 [main] DEBUG o.s.d.m.c.i.MongoPersistentEntityIndexCreator - Analyzing class class com.journaldev.spring.mongodb.model.Person for index information.
02:27:34.516 [main] DEBUG o.s.data.mongodb.core.MongoTemplate - Inserting DBObject containing fields: [_class, _id, name, address] in collection: Person
02:27:34.520 [main] DEBUG o.s.data.mongodb.core.MongoDbUtils - Getting Mongo Database name=[journaldev]
Generated ID=53f50bbe0364b65dbc0c4753
02:27:34.532 [main] DEBUG o.s.data.mongodb.core.MongoTemplate - findOne using query: { "_id" : "53f50bbe0364b65dbc0c4753"} fields: null for class: class com.journaldev.spring.mongodb.model.Person in collection: Person
02:27:34.533 [main] DEBUG o.s.data.mongodb.core.MongoDbUtils - Getting Mongo Database name=[journaldev]
02:27:34.535 [main] DEBUG o.s.data.mongodb.core.MongoTemplate - findOne using query: { "_id" : { "$oid" : "53f50bbe0364b65dbc0c4753"}} in db.collection: journaldev.Person
Retrieved Person=53f50bbe0364b65dbc0c4753::PankajKr::Bangalore, India
02:27:34.543 [main] DEBUG o.s.data.mongodb.core.MongoTemplate - Saving DBObject containing fields: [_class, _id, name, address]
02:27:34.543 [main] DEBUG o.s.data.mongodb.core.MongoDbUtils - Getting Mongo Database name=[journaldev]
02:27:34.545 [main] DEBUG o.s.data.mongodb.core.MongoTemplate - findOne using query: { "_id" : "53f50bbe0364b65dbc0c4753"} fields: null for class: class com.journaldev.spring.mongodb.model.Person in collection: Person
02:27:34.545 [main] DEBUG o.s.data.mongodb.core.MongoDbUtils - Getting Mongo Database name=[journaldev]
02:27:34.546 [main] DEBUG o.s.data.mongodb.core.MongoTemplate - findOne using query: { "_id" : { "$oid" : "53f50bbe0364b65dbc0c4753"}} in db.collection: journaldev.Person
Retrieved Person after update=53f50bbe0364b65dbc0c4753::David::SFO, USA
02:27:34.549 [main] DEBUG o.s.data.mongodb.core.MongoDbUtils - Getting Mongo Database name=[journaldev]
02:27:34.550 [main] DEBUG o.s.data.mongodb.core.MongoTemplate - Remove using query: { "_id" : { "$oid" : "53f50bbe0364b65dbc0c4753"}} in collection: Person.
Number of records deleted=1
02:27:34.553 [main] INFO  o.s.c.s.ClassPathXmlApplicationContext - Closing org[email protected]7a187814: startup date [Thu Aug 21 02:27:33 GMT+05:30 2014]; root of context hierarchy
02:27:34.553 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
02:27:34.553 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Destroying singletons in org.s[email protected]3f64b09c: defining beans [mongo,org.springframework.beans.factory.config.CustomEditorConfigurer#0,org.springframework.beans.factory.config.CustomEditorConfigurer#1,org.springframework.beans.factory.config.CustomEditorConfigurer#2,mongoDbFactory,mongoTemplate,personDAO]; root of factory hierarchy
02:27:34.554 [main] DEBUG o.s.b.f.s.DisposableBeanAdapter - Invoking destroy() on bean with name 'mongoDbFactory'
02:27:34.554 [main] DEBUG o.s.b.f.s.DisposableBeanAdapter - Invoking destroy() on bean with name 'mongo'

Notice that when Spring context is closed, it’s taking care of closing the MongoDB connections too, so we don’t need to worry about that.

Also I am providing MongoDB Collection name in each of the queries, we can skip that if the collection name confirms to java naming convention. For example, for “Person” and “PersonAddress” objects default collection name used by Spring MongoDB would be “person” and “personAddress” respectively.

We can also use org.springframework.data.mongodb.core.mapping.Document annotation with Model class to define the collection name to be used for saving the document.

Spring Data MongoDB Annotation Based Configuration

If you want to use annotation based configuration, below Configuration class can be used for reference.

SpringMongoDBConfiguration.java


package com.journaldev.spring.mongodb.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import com.mongodb.MongoClient;
@Configuration
public class SpringMongoDBConfiguration {
	public @Bean MongoDbFactory getMongoDbFactory() throws Exception {
		return new SimpleMongoDbFactory(new MongoClient("localhost",27017), "journaldev");
	}
	public @Bean MongoTemplate getMongoTemplate() throws Exception {
		MongoTemplate mongoTemplate = new MongoTemplate(getMongoDbFactory());
		return mongoTemplate;
	}
}

We would need other configurations too to inject MongoTemplate bean into our DAO implementation class, I am leaving that part to you.

Using MongoOptions for MongoDB Connection Options

We can use MongoOptions to define MongoDB options in spring bean configuration file like below. There are some other configuration options too, that you can check for optimizing your connections.


<mongo:mongo host="localhost" port="27017">
    <mongo:options connections-per-host="4"
                   connect-timeout="1000"
                   max-wait-time="1500"
                   auto-connect-retry="true"
                   socket-keep-alive="true"
                   socket-timeout="1500"
                   write-fsync="true" />
  </mongo:mongo>

Spring Data MongoDB Example Summary

I hope this tutorial was good enough to get you started with Spring Data MongoDB, it’s not feasible to cover everything. You should look more into Query, Criteria and MongoTemplate methods to learn more. You can download the final project from below link.

By admin

Leave a Reply

%d bloggers like this: