Computer scienceBackendSpring BootSpring DataMongoDB

Mapping classes to JSON documents

9 minutes read

MongoDB stores data in flexible JSON-like documents, which means fields can vary from document to document and data structure can be changed over time. Today we are going to explore the basic principles of converting MongoDB document models to Java or Kotlin classes and vice versa using Spring Data.

Entities as Documents

MongoDB stores data as documents in collections. A document is a set of key-value pairs and a collection is a group of MongoDB documents. Collections don't enforce a schema, so different documents within a collection can have varying fields.

If you want Spring Data to store a class as a MongoDB document, mark that class with the @Document annotation. This Spring-specific annotation can have several parameters:

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

@Document(collection = "fleet")
public class Starship {
    //...
}

The collection parameter specifies the name of the MongoDB collection where the documents will be stored. If you don't specify it, the class name (with the first character in lowercase) will be used as the collection name.

Each entity must have an identity. The @Id annotation from the org.springframework.data.annotation package lets you mark the field in your class that will act as the document's unique identifier in MongoDB. The @Id field can be various types, including String, BigInteger, and ObjectId, a special class from the org.bson.types package that represents the MongoDB object identifier.

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

@Document(collection = "fleet")
public class Starship {
    @Id
    private String id;

    // getter and setter
}

Remember to not mix the @Id annotation from the org.springframework.data.annotation package with the @Id annotation from the jakarta.persistence package. Make sure you import the correct one.

If the id field is null, MongoDB will generate it automatically. If it already has a value, that value will remain intact. This keeps the process of creating new documents and updating existing documents straightforward.

@Field Annotation

The @Field annotation allows you to define how the field will be represented in the MongoDB document. This is useful when you need the field name in the JSON document to be different from the field name in your class, want to explicitly write null values to the MongoDB document, or need to explicitly set the MongoDB data type for a given field.

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

@Document(collection = "fleet")
public class Starship {
    @Id
    private String id;

    @Field(name = "ship_name")
    private String name;

    @Field(name = "crew", targetType = FieldType.STRING)
    private Integer personnel;

    // getters and setters
}

In the above example, the field name will become ship_name in the JSON document, and the field personnel will be named crew and saved as a string.

{
  "_id": {  "$oid": "656738a660762513b35f868e"  },
  "ship_name": "Galaxy Explorer",
  "crew": "2000",
  "_class": "org.example.Starship"
}

Embedded Classes

Spring Data MongoDB enables you to embed classes and collections in your documents. If you include a class as a field in another class, that inner class will be embedded in the JSON document. Here's an example:

public class Captain {
    private String name;

    // getter and setter
}

@Document(collection = "fleet")
public class Starship {
    @Id
    private String id;

    @Field(name = "ship_name", order = 2)
    private String name;

    @Field(name = "crew", targetType = FieldType.STRING)
    private Integer personnel;

    private Captain captain;

    // getters and setters
}

In this case, the Captain class becomes an object embedded within the Starship document:

{  "_id": {    "$oid": "65673d523b85a65d165aecd2"  },
  "ship_name": "Galaxy Explorer",
  "crew": "2000",
  "captain": {
    "name": "Jane"
  },
  "_class": "org.example.Starship"
}

Embedded Collections

Similar to classes, if you include a collection of objects or values, these will be embedded as an array within the JSON document:

@Document(collection = "fleet")
class Starship {
    @Id
    private String id;

    @Field(name = "ship_name", order = 2)
    private String name;

    @Field(name = "crew", targetType = FieldType.STRING)
    private Integer personnel;

    private Captain captain;

    private List<String> waypoints;

    // getters and setters
}

In this situation, each string in the waypoints list will be embedded as an array string within the Starship document:

{
  "_id": {    "$oid": "65673ebd0948304a72ea1eab"  },
  "ship_name": "Galaxy Explorer",
  "crew": "2000",
  "captain": {
    "name": "Jane"
  },
  "waypoints": [
    "Sun",
    "Vega",
    "Sirius"
  ],
  "_class": "org.example.Starship"
}

Null and Non-persistent Fields

By default, Spring Data doesn't write null fields to JSON documents to save space. You can change this by setting the write parameter of the @Field annotation to Field.Write.ALWAYS:

@Field(write = Field.Write.ALWAYS)
private String destination;

In this case, if the destination field is null, it will still be saved in the database.

There may be times when you have fields in your class that you don't want to save in the database. Mark these fields with the @Transient annotation, and Spring Data will exclude them:

@Transient
private String currentWaypoint;

Conclusion

Today, you've learned how to map Java and Kotlin classes to JSON documents using Spring Data. Specifically, you've discovered the @Document, @Id and @Field annotations, gotten to know their parameters, and understood how to set field names and data types in JSON documents. You've also learned how to map embedded classes and collections and discovered how to manage null and non-persistent fields.

7 learners liked this piece of theory. 0 didn't like it. What about you?
Report a typo