Sunday, August 24, 2014

Spring Data with MongoDB

MongoDB is an open source document database and one of most popular NoSQL databases. See mongdb official page for more details.
Spring data has an integration with the MongoDB.

How to use

Add the following dependencies to use with maven.
  • Spring-data-mongodb
  • mongodb java driver
  • Spring context related modules (As spring requires these)
  <!-- Spring framework -->
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-core</artifactId>
   <version>3.2.2.RELEASE</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
   <version>3.2.2.RELEASE</version>
  </dependency>

  <!-- mongodb java driver -->
  <dependency>
   <groupId>org.mongodb</groupId>
   <artifactId>mongo-java-driver</artifactId>
   <version>2.11.0</version>
  </dependency>
  <dependency>
   <groupId>org.springframework.data</groupId>
   <artifactId>spring-data-mongodb</artifactId>
   <version>1.5.2.RELEASE</version>
  </dependency>
  <dependency>
   <groupId>cglib</groupId>
   <artifactId>cglib</artifactId>
   <version>2.2.2</version>
  </dependency>

Configuration

Configuration can be done in two ways a) Using @Configuration and b) Using Spring XML

a) Using Configuration

Create a class annotated with Configuration and add two methods : mongoDbFactory() and mongoTemplate() like this.
package com.test.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 SpringMongoConfig
{
    public @Bean
    MongoDbFactory mongoDbFactory() throws Exception
    {
        return new SimpleMongoDbFactory(new MongoClient(), "sample");
    }

    public @Bean
    MongoTemplate mongoTemplate() throws Exception
    {

        MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory());

        return mongoTemplate;

    }
}

How to create context

Call the above configuration using : AnnotationConfigApplicationContext
    AbstractApplicationContext ctx = new AnnotationConfigApplicationContext(SpringMongoConfig.class);
    MongoOperations mongoOperation = (MongoOperations)ctx.getBean("mongoTemplate");

b) Using Spring XML File

See the following spring-config.xml file to configure mongo DB template
<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"
 xsi:schemaLocation="http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-3.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/beans
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

 <mongo:mongo host="127.0.0.1" port="27017" />
 <mongo:db-factory dbname="sample" />

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

</beans>

How to create context

Create the application context using spring-config.xml as follows:
     AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");
     MongoOperations mongoOperation = (MongoOperations) ctx.getBean("mongoTemplate");     
Any one of the options (a) and (b) is enough. XML configuration is always preferable.

MongoDB Document

Map the MongoDB Document using a class annotated using @Document annotation
package com.test.mongodb.entity;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection = "person")
public class Person
{
    @Id
    private String id;
    private String name;
    private int age;
    private double salary;
    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 int getAge()
    {
        return age;
    }
    public void setAge(int age)
    {
        this.age = age;
    }
    public double getSalary()
    {
        return salary;
    }
    public void setSalary(double salary)
    {
        this.salary = salary;
    }
    @Override
    public String toString()
    {
        String str = "Person details : [id:%s, name:%s ,age:%d, salary:%f]";
        return String.format(str, id,name,age,salary);
    }
}

Operations

Operations on the MongoDB Document can be performed using using mongoOperation object.

Application

The application class will be as follows
        Person p = new Person();
        p.setId("10");
        p.setName("Joe");
        p.setAge(30);
        p.setSalary(3000.00);
        mongoOperation.save(p);
        
        //Create Query for fetching the data
        Query sQuery = new Query(Criteria.where("salary").lte(3000.00));
        Person person = mongoOperation.findOne(sQuery, Person.class);
        if(person != null)
            System.out.println("After inserting : Found Person : " + person);
        else
            System.out.println("No person found");
        
        mongoOperation.updateMulti(sQuery, 
                Update.update("salary", "40000"),Person.class);
        
        List<Person> list = mongoOperation.findAll(Person.class);
        System.out.println("After updating Size is "+(list == null ? 0: list.size()));
        if(list != null)
        {
            for(Person pr : list)
            {
                System.out.println(pr);
            }
        }
        
        Query rQuery = new Query(Criteria.where("id").is("10"));
        mongoOperation.remove(rQuery, Person.class);
        
        list = mongoOperation.findAll(Person.class);
        System.out.println("After deleteing one Person. Size is "+(list == null ? 0: list.size()));
        if(list != null)
        {
            for(Person pr : list)
            {
                System.out.println(pr);
            }
        }
        ctx.close();
Output of the above program will be :
After inserting : Found Person : Person details : [id:10, name:Joe ,age:30, salary:3000.000000]
After updating Size is 2
Person details : [id:2, name:Joe ,age:30, salary:40000.000000]
Person details : [id:10, name:Joe ,age:30, salary:40000.000000]
After deleteing one Person. Size is 1
Person details : [id:2, name:Joe ,age:30, salary:40000.000000]
Happy Learning!!!!