Using Spring Data MongoDB

Spring Data MongoDB provides a great third party support based on standard MongoDB Java Driver.

Dependencies

Following dependencies are required. Check for latest version via Nexus Central Repository:

  1. spring-data-mongodb
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-mongodb</artifactId>
      <version>1.2.1.RELEASE</version>
    </dependency>
    
  2. mongo-java-driver
    <dependency>
      <groupId>org.mongodb</groupId>
      <artifactId>mongo-java-driver</artifactId>
      <version>2.11.1</version>
    </dependency>
    

Setup Mongo Connection, Template and Repository Scanning

This is similar idea with setting up db datasource. In this example the mongo database server is located at localhost:27017 (default). The MongoDB database name used is enrollment. The <mongo:repositories ...> tag specifies the base package to scan for repository classes

<?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:mongo="http://www.springframework.org/schema/data/mongo"
  xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.2.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

  <mongo:mongo host="localhost" port="27017" />

  <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
    <constructor-arg ref="mongo" />
    <constructor-arg value="enrollment" />
  </bean>
  
  <mongo:repositories base-package="com.gerrydevstory.enrollment"/>
</beans>

Domain / Entity Class

Example on this post will be based on a simple Student entity class with only id and name field:

import org.springframework.data.annotation.Id;

public class Student {
  @Id private String id;
  private String name;
  // getters & setters..
}

Without explicit configuration this entity class will be mapped into MongoDB collection name student. To override this default behavior use @Document(collection = "...") annotation.

Repository Class

Simply add an interface extending Spring Data Repository interface. Below sample uses PagingAndSortingRepository, which extends CrudRepository which provides most basic operation. The type parameter specifies this repository operates over Student entity, with the ID type being String. Spring Data will automatically generate an implementation of this interface.

public interface StudentRepository extends PagingAndSortingRepository<Student, String> {

}

This repository can now be injected into controllers:

@Controller
@RequestMapping("/student")
public class StudentController {

  @Autowired private StudentRepository studentRepository;

  @RequestMapping(method = GET)
  public String get(Model model) {
    Iterable<Student> students = studentRepository.findAll();
    return "student";
  }

  @RequestMapping(value = "/new", method = POST)
  public String addNew(@ModelAttribute("student") Student student) {
    studentRepository.save(student);
  }

  ...
}

Read More

Learn more about Spring Data and MongoDB:

Connecting to MongoDB On Visual C++ / Visual Studio 2010

Environment / Dependencies:

  • Windows 7 64bit
  • Visual Studio 2010 (Win32-Release target project)
  • MongoDB 2.2.3
  • Git

Visual Studio 2010 sample client project doesn’t appear to compile on the latest version of mongodb source code (2.4.3 at the time of this writing). It seems the last working sample is version 2.2.3. Follow these steps to compile and use it as your starting point

  1. Clone the source code from git:
    git clone git://github.com/mongodb/mongo.git C:\mongodbsrc
  2. Open command prompt to C:\mongodbsrc, switch to version 2.2.3 by running:
    git checkout r2.2.3
  3. Double click C:\mongodbsrc\src\mongo\client\examples\simple_client_demo.vcxproj. If Visual Studio prompt to upgrade, don’t do it
  4. Compile the project on visual studio and test it. Use this as your starting point
  5. If you’re trying to copy the settings into your own project, pay particular attention to following items:
    • Boost cpp files and mongo_client_lib.cpp inclusion
    • VC++ Directories
    • C/C++ –> General –> Additional Include Directories
    • C/C++ –> Preprocessor –> Preprocessor Definitions
    • Linker –> Input –> Additional Dependencies
    • Additional preprocessor definitions only for these boost files: thread.cpp, tss_dll.cpp, tss_pe.cpp
    • Different Output Files for utf8_codecvt_facet.cpp file

Quick Cheat Sheet

// Connecting to mongodb on c++
mongo::DBClientConnection conn;
conn.connect("localhost");

// mongo shell
db.mycoll.insert({name: "Gerry", age: "25"})

// c++
conn.insert("mydb.mycoll", BSON("name" << "Gerry" << "age" << 25));

// mongo shell
db.mycoll.update({name: "Gerry"}, {name: "Gerry", age: "30"}, {upsert: "true"})

// c++
conn.update("mydb.mycoll", BSON("name" << "Gerry"), BSON("name" << "Gerry" << "age" << 30), 1);

Documentations:

Auto Incrementing Field On Spring Data MongoDB

MongoDB came with all sophisticated ObjectId generation feature, but often you just jumped the ship from relational database, and you still want an easy to read / communicate numeric identifier field which automatically increments every time new record is inserted.

One neat suggestion from MongoDB tutorial is to use a counter collection with a ‘counter name’ as its id, and a ‘seq’ field to store the last used number:

db.counters.insert({
  _id: "users",
  seq: 0
})

Then use findAndModify function to increment and obtain the next value.

db.counters.findAndModify({
	query: { _id: name },
	update: { $inc: { seq: 1 } },
	new: true
})

When developing using Spring Data MongoDB, this neat trick can be written as a simple service. Here I used the collection name as the counter name so it’s easy to guess / remember.

import static org.springframework.data.mongodb.core.query.Query.*;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import static org.springframework.data.mongodb.core.FindAndModifyOptions.*;

@Service
public class CounterService {
  @Autowired private MongoOperations mongo;
  
  public int getNextSequence(String collectionName) {

    Counter counter = mongo.findAndModify(
      query(where("_id").is(collectionName)), 
      new Update().inc("seq", 1),
      options().returnNew(true),
      Counter.class);
      
    return counter.getSeq();
  }
}

Counter is just a simple class representing the collection. Please beware the usage of int data type, this will limit to 2^31 entries maximum.

@Document(collection = "counters")
public class Counter {
  @Id private String id;
  private int seq;
  /* getters & setters .. */
}

Then when inserting a new entry (with help of Spring MongoDB Repository support), just set the id field like this before you save it

User newUser = new User();
newUser.setId(counterService.getNextSequence("users"));
newUser.setUsername(username);
newUser.setPassword(password);

userRepository.save(newUser);

You’ll get an incrementing simple numeric id each time you insert new object