Spring Data MongoDB Example
In this example, we will demonstrate how to connect Spring Data with MongoDb. MongoDb is also a document based NoSql Database like Solr, which we demonstrated past week.
Spring Data MongoDb is the module of Spring Data that provides support for MongoDb. As with the other modules demonstrated in this series, this module too provides supports both for derived queries(based on the method name) and the annotated query.
Let´s get started with the setup:
1. How to configure and manage a MongoDb using Spring Data
Install Mongodb depending upon your system from here.
Point to the bin
of the installed MongoDb, which is Program Files
in Windows. Then run the following command:
mongo --dbpath C:\MongoDb\Data
This command starts the MongoDb Server with the repository location at the path specified in the command above. However, the folders should already be present otherwise the server will throw Invalid Directory
error. The default port for MongoDb is 271017
.
Now that the Mongo
server is up and running, we will setup the application environment.
Create a simple Maven Project in eclipse IDE. We are using the below pom.xml
to manage the dependencies for MongoDb from Spring data.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>SpringDataMongoDbExample</groupId> <artifactId>SpringDataMongoDbExample</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>1.7.2.RELEASE</version> </dependency> </dependencies> </project>
Eclipse will download the required JAR files and add the dependencies in the project classpath. Now that the project is setup and dependencies imported, we can begin writing the actual code.
We start by creating the entities that will be persisted to the Mongo Database.
Person.java
package com.jcg.examples.entity; import java.util.ArrayList; import java.util.List; import org.springframework.data.annotation.Id; import org.springframework.data.annotation.PersistenceConstructor; import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.mapping.Document; @Document(collection="person") public class Person { @Id private Long personId; private String name; private int age; @DBRef(db="address") private List<Address> addresses = new ArrayList<>(); public Person() {} @PersistenceConstructor public Person(Long personId, String name, int age) { super(); this.personId = personId; this.name = name; this.age = age; } public Long getPersonId() { return personId; } public void setPersonId(Long personId) { this.personId = personId; } 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 List<Address> getAddresses() { return addresses; } public void setAddresses(List<Address> addresses) { this.addresses = addresses; } @Override public String toString() { return "Person [personId=" + personId + ", name=" + name + ", age=" + age + ", addresses=" + addresses + "]"; } }
@Document
is used to denote the collection in which the data will be persisted. If it is not mentioned, the data is saved in the collection which has the same name as the Entity Class Name.
@Id
maps the property annotated with it to the _id
column of the collection. In case no property is annotated with @Id
, the property with the name id will be mapped to the _id
. In case there is now property with that name, a column will be generated by the Mongo Driver, but the value will not available in the PoJo.
@DBRef
is used to relate an existing entity to the current entity. However, unlike the case with Relational Databases, if we save the host entity it does not save the related entity. It has to be persisted separately.
@PersistenceConstructor
is used to mark the constructor which is to be used for creating entities when fetching data from the Mongo Server.
Here is the linked entity Address
.
Address.java
package com.jcg.examples.entity; import org.springframework.data.annotation.Id; import org.springframework.data.annotation.PersistenceConstructor; import org.springframework.data.mongodb.core.mapping.Document; @Document(collection="address") public class Address { @Id private long addressId; private String address; private String city; private String state; private long zipcode; public Address() { System.out.println("CAlling default cons"); } @PersistenceConstructor public Address(long addressId, String address, String city, String state, long zipcode) { super(); this.addressId = addressId; this.address = address; this.city = city; this.state = state; this.zipcode = zipcode; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getState() { return state; } public void setState(String state) { this.state = state; } public long getZipcode() { return zipcode; } public void setZipcode(long zipcode) { this.zipcode = zipcode; } @Override public String toString() { return "Address [address=" + address + ", city=" + city + ", state=" + state + ", zipcode=" + zipcode + "]"; } }
Now we will create a Repository for each of the entity defined above which will help us in persisting the respective Entities to the MongoDb Server.
PersonRepo.java
package com.jcg.examples.repo; import org.springframework.data.mongodb.repository.Query; import org.springframework.data.repository.CrudRepository; import com.jcg.examples.entity.Person; public interface PersonRepo extends CrudRepository<Person, Long> { @Query("{'name' : ?0}") public Iterable<Person> searchByName(String personName); }
Spring Data Module provides us with a number of inbuilt method for manipulating the Data. We need not write the queries for basic data manipulation and reading. It is achieved by extending the CrudRepository
interface and declaring the proper Generics as per the Entity, which in our case is the <Person, Long>
.
For executing custom written queries, the developer can create his own method by specifying the Query using the @Query
annotation. In the above class, we have annotated the method, searchByName
with the said annotation. This method returns the Person Entity by querying the name field of the Person
Collection from the Server.
Here’s the AddressRepo
AddressRepo.java
package com.jcg.examples.repo; import org.springframework.data.repository.CrudRepository; import com.jcg.examples.entity.Address; public interface AddressRepo extends CrudRepository
The last and the most important part is to configure the Spring Container using the spring-config.xml
:
Spring-config.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" 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"> <!-- Configure the Mongo Server --> <mongo:mongo id="mongo" host="localhost" port="27017"/> <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg ref="mongo"/> <constructor-arg name="databaseName" value="jcg"/> </bean> <mongo:repositories base-package="com.jcg.examples.repo"></mongo:repositories> </beans>
- Line 15: Configure the Mongo Server by providing the server and the Port on which it is running.
- Line 17: The
mongoTemplate
is used as a dependency for creating the repositories which we discussed above. - Line 22: Scan the packages for initializing Mongo Bean Repositories.
Now that all is set, let’s run the application and test out the code! Here’s Application
class that loads the XML
file to instantiate the Spring Container and execute a few queries.
Application.java
package com.jcg.examples.test; import java.util.List; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.ClassPathResource; import com.jcg.examples.entity.Address; import com.jcg.examples.entity.Person; import com.jcg.examples.repo.AddressRepo; import com.jcg.examples.repo.PersonRepo; public class Application { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new ClassPathResource("spring-config.xml").getPath()); PersonRepo personRepo = context.getBean(PersonRepo.class); AddressRepo addressRepo = context.getBean(AddressRepo.class); Person personAchilles = new Person(); personAchilles.setPersonId(1l); personAchilles.setName("Achilles"); personRepo.save(personAchilles); Person personHektor = new Person(); personHektor.setPersonId(2l); personHektor.setName("Hektor"); Address address = new Address(1,"221b Baker Street","London NW1","London",12345l); List<Address> addresses = personHektor.getAddresses(); addresses.add(address); personAchilles.setAddresses(addresses); addressRepo.save(address); personRepo.save(personHektor); Iterable<Person> personList = personRepo.findAll(); System.out.println("Person List : "); for (Person person : personList) { System.out.println(person); } System.out.println("Person Record with name Hektor is "+personRepo.searchByName("Hektor")); context.close(); } }
In the Application
we create two instances of Person
and persist them. However, the second instance also has a linked Address
instance to it, which we persist separately by calling the save
method of the AddressRepo
class.
Then we iterate all the elements stored in the Person collection. We have also successfully searched for the Person named Hektor from the collection using custom query and the @Query
annotation.
Here’s the sample output of the program:
Person List : Person [personId=1, name=Achilles, age=0, addresses=[]] Person [personId=2, name=Hektor, age=0, addresses=[Address [address=221b Baker Street, city=London NW1, state=London, zipcode=12345]]] Person Record with name Hektor is [Person [personId=2, name=Hektor, age=0, addresses=[Address [address=221b Baker Street, city=London NW1, state=London, zipcode=12345]]]]
2. Download the Source Code
Here we demonstrated how to configure and manage a MongoDb using Spring Data.
You can download the source code of this example here: SpringDataMongoDbExample.zip