Java Spring - Handling Data with MongoDB
In this tutorial, we will:
- Get acquainted with MongoDB
- Persist documents with MongoDB
- Create Update operations
- Look at Multi operations in MongoDB
- Upsert data in Mongo
As already mentioned in our previous articles of the series, Spring framework is an open source Java platform that provides MVC infrastructure support for developing robust Java applications very easily and very rapidly using recommended MVC pattern.
MongoDB
MongoDB is an open-source database developed by MongoDB Inc. Key points to note about how MongoDB works are:
- It stores data in JSON-like documents that can vary in structure.
- MongoDB uses dynamic schemas, which means that we can create records without first defining the structure of the fields of their types.
- The structure of a record can be changed simply by adding new fields or deleting existing ones.
The mentioned data model gives us the ability to represent hierarchical relationships, to store arrays, and other more complex structures easily.
Persisting documents with MongoDB
Let’s start integrating MongoDB into our Spring project. To use MongoDB, we’re going to add it in our project using Maven dependency. Here it goes:
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.7.2.RELEASE</version>
</dependency>
With Java Driver for Mongo present in our project, we can start working on Mongo queries in Java. We need to configure the Mongo in our project, for this, let’s add a MongoConfig class.
@Configuration
public class MongoConfig extends AbstractMongoConfiguration {
@Override
protected String getDatabaseName() {
return "test";
}
@Override
public Mongo mongo() throws Exception {
return new MongoClient("127.0.0.1", 27017);
}
@Override
protected String getMappingBasePackage() {
return "com.discoversdk";
}
}
Configuration for MongoRepository
We’ll build on the configuration we already created in previous section and add a new annotation into the mix:
@EnableMongoRepositories(basePackages = "org.discoversdk.repository")
Creating Data a access repository
Just like in Spring Data JPA, we can create repository interfaces to access data.
public interface UserRepository extends MongoRepository<User, String> {
//
}
Now we can auto-wire this UserRepository and use operations from MongoRepository or add custom operations.
In a typical Java application, we write a class that implements UserRepository and craft the queries ourself. What makes Spring Data MongoDB so useful is the fact that we don’t have to create this implementation. Spring Data MongoDB creates it on the fly when we run the application.
Creating simple queries
Spring Data MongoDB focuses on storing data in MongoDB. It also inherits functionality from the Spring Data Commons project, such as the ability to derive queries. So, we don’t have to learn the query language of MongoDB—we can simply write a handful of methods and the queries will be written for us.
To see how this works, create a repository interface that queries User documents.
import java.util.List;
import org.springframework.data.mongodb.repository.MongoRepository;
public interface UserRepository extends MongoRepository<User, String> {
public User findByFirstName(String firstName);
public List<User> findByLastName(String lastName);
}
UserRepository extends the MongoRepository interface and plugs in the type of values and id it works with: User and String. Out-of-the-box, this interface comes with many operations, including standard CRUD operations (create-read-update-delete).
We can define other queries as needed by simply declaring their method signature. In this case, we add findByFirstName, which essentially seeks documents of the type User and finds the one that matches on firstName.
We also have findByLastName to find a list of people by last name.
Insert
Let’s start with the insert operation; let’s also start with a completely empty database:
{}
Now if we insert a new user:
User user = new User();
user.setName("Liran");
mongoTemplate.insert(user, "user");
The database will look like this:
{
"_id" : ObjectId("33b1fed5830b667a8w1ca43a"),
"_class" : "com.discoversdk.model.User",
"name" : "Liran"
}
Update
Let’s now look at save with update semantics, operating on an existing entity:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.discoversdk.model.User",
"name" : "Jack"
}
Now, when we save the existing user – we will update it:
user = mongoTemplate.findOne(
Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
mongoTemplate.save(user, "user");
The database will look like this:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.discoversdk.model.User",
"name" : "Jim"
}
As you can see, in this particular example, save uses the semantics of update, because we use an object with the given _id.
Delete
Now, let’s move to the delete operation. The database, before the deletion was executed, looks like this:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.discoversdk.model.User",
"name" : "Benn"
}
After we run the delete operation,
userRepository.delete(user);
Now, the database will look like:
{}
FindOne
In Mongo, we can find a single unit of data using the findOne() operation, simply on the entity interface. Let’s look at an example:
userRepository.findOne(user.getId());
The result will look like:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "org.baeldung.model.User",
"name" : "Chris"
}
Exists
Many a times in our application, we need to check if a particular user already exists in our database or not. So that we don’t have to fetch complete user data, we can just run a check. Let’s see how it is done. Currently, database have one user as:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "org.baeldung.model.User",
"name" : "Chris"
}
When we run an operation as:
boolean isExists = userRepository.exists(user.getId());
This will of course return true.
FindAll With pagination
Suppose we have a lot of data in our database and now, we want to show it to a user, all of it! Fetching lots data at once can be a heavy operation and can significantly decrease the performance of our application.
We can save that performance hit by introducing a simple concept called Pagination. In Pagination, data is not fetched all at once. But it is divided in pages and only 1 page is fetched at a time. Each page can contain any number of records, say 20 or 30.
Let’s see how it is done:
Pageable pageableRequest = new PageRequest(0, 1);
Page<User> page = userRepository.findAll(pageableRequest);
List<User> users = pages.getContent();
Result will fetch just 1 record at a time:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "org.baeldung.model.User",
"name" : "Brendan"
}
It is important to explain the parameters accepted by PageRequest.
- First parameter, 0 in this case, is the page number we are currently trying to fetch. If this was 1, 0th page will be skipped.
- Next parameter is 1, indicating number of documents this request should return.
Annotations
Finally, let’s also go over the simple annotations that Spring Data uses to drive these API operations.
@Id
private String id;
The field level @Id annotation can decorate any type, including long and String.
If the value of the @Id field is not null, it’s stored in the database as-is—otherwise, the converter will assume you want to store an ObjectId in the database (either ObjectId, String or BigInteger work).
Next – @Document:
@Document
public class User {
//
}
This annotation simply marks a class as being a domain object that needs to be persisted to the database, along with allowing us to choose the name of the collection to be used.
Conclusion
This article was a quick but comprehensive introduction to using MongoDB with Spring Data, both via the MongoTemplate API as well as making use of MongoRepository.
In the next article, we will continue our journey to learn more NoSQL databases in Spring framework like Reddis and Neo4J.
Stop by DiscoverSDK.com for Java SDKs.
Recent Stories
Top DiscoverSDK Experts
Compare Products
Select up to three two products to compare by clicking on the compare icon () of each product.
{{compareToolModel.Error}}
{{CommentsModel.TotalCount}} Comments
Your Comment