For AI agents: a documentation index is available at https://www.mongodb.com/docs/llms.txt — markdown versions of all pages are available by appending .md to any URL path.
Docs Menu

Create Entities to Represent Collections

In this guide, you can learn how to create Hibernate ORM entities that represent MongoDB collections. Entities are Java classes that define the structure of your data. When using the Hibernate ORM extension, you can map each entity to a MongoDB collection and use these entities to interact with the collection's documents.

Tip

Entities Tutorial

To view a tutorial that shows how to model one-to-many relationships by using entities and the Hibernate ORM extension, see the Modeling Relationships With Hibernate ORM and MongoDB Foojay blog post.

MongoDB organizes and stores documents in a binary representation called BSON that allows for flexible data processing. This section describes the Hibernate ORM extension's support for BSON fields, which you can include in your entities.

Tip

To learn more about how MongoDB stores BSON data, see BSON Types in the MongoDB Server manual.

The following table describes supported BSON field types and their Hibernate ORM extension equivalents that you can use in your Hibernate ORM entities:

BSON Field Type
Extension Field Type
BSON Description

null

null

Represents a null value or absence of data.

Binary

byte[]

Stores binary data with subtype 0.

String

char, java.lang.Character, java.lang.String, char[], java.time.ZoneId, java.time.ZoneOffset, or java.util.TimeZone

Stores UTF-8 encoded string values. The ZoneId and TimeZone types store their ID, such as Europe/Paris. The ZoneOffset type stores its offset ID, such as +02:00.

Int32

int, java.lang.Integer, or java.time.Year

Stores 32-bit signed integers.

Int64

long or java.lang.Long

Stores 64-bit signed integers.

Double

double or java.lang.Double

Stores floating-point values.

Boolean

boolean or java.lang.Boolean

Stores true or false values.

Decimal128

java.math.BigDecimal or java.time.Duration

Stores 28-bit decimal values. java.time.Duration values store the duration in nanoseconds.

ObjectId

org.bson.types.ObjectId

Stores unique 12-byte identifiers that MongoDB uses as primary keys.

Date

java.time.Instant

Stores dates and times as milliseconds since the Unix epoch.

Object

@org.hibernate.annotations.Struct aggregate embeddable

Stores embedded documents with field values mapped according to their respective types. @Struct aggregate embeddables might also contain array or Collection attributes.

Array

Array, java.util.Collection (or subtype) of supported types

Stores array values with elements mapped according to their respective types. Character arrays require setting the hibernate.type.wrapper_array_handling configuration property.

Note

@JdbcTypeCode Annotation Is Not Supported

The Hibernate ORM extension does not support the @org.hibernate.annotations.JdbcTypeCode annotation and throws an exception if you use this annotation to override a field's type mapping.

Hibernate ORM serializes any Java type that implements java.io.Serializable to binary data when it has no other mapping for that type. To prevent your data from being stored in this format, the Hibernate ORM extension rejects the following types and throws an exception when your application starts. This check applies to primary keys, ordinary fields, embeddable attributes, and collection elements.

The following table describes unsupported field types and their supported alternatives:

Category
Unsupported Types
Supported Alternative

Date and Time

java.util.Calendar, java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp, java.time.LocalTime, java.time.LocalDateTime, java.time.ZonedDateTime, java.time.OffsetTime, java.time.OffsetDateTime

Use java.time.Instant.

BSON Values

org.bson.types.BSONTimestamp, org.bson.types.Binary, org.bson.types.Code, org.bson.types.CodeWithScope, org.bson.types.CodeWScope, org.bson.types.MinKey, org.bson.types.MaxKey, org.bson.types.Symbol, org.bson.types.Decimal128

Use byte[] for binary data and java.math.BigDecimal for decimal values. The other types have no equivalent.

BSON Documents

org.bson.Document, org.bson.BsonDocument, org.bson.RawBsonDocument, org.bson.BsonDocumentWrapper

Use an @org.hibernate.annotations.Struct aggregate embeddable.

Identifiers

java.util.UUID

Use org.bson.types.ObjectId or java.lang.String.

To create an entity that represents a MongoDB collection, create a new Java file in your project's base package directory and add your entity class to the new file. In your entity class, specify the fields you want to store and the collection name.

The name element of the @jakarta.persistence.Table annotation represents your MongoDB collection name. You can also set the optional schema element to prefix the collection name, as described in the Schema Qualifiers section of this guide. Use the following syntax to define an entity:

@Entity
@Table(name = "<collection name>")
public class <EntityName> {
@Id
// Specify your primary key field here
private <field type> <field name>;
// Include additional fields here
private <field type> <field name>;
// Parameterized constructor
public <EntityName>(<parameters>) {
// Initialize fields here
}
// Default constructor
public <EntityName>() {
}
// Getter and setter methods
public <field type> get<FieldName>() {
return <field name>;
}
public void set<FieldName>(<field type> <field name>) {
this.<field name> = <field name>;
}
}

To use your entities, you can query them in your application files. To learn more about CRUD operations in the Hibernate ORM extension, see the Perform CRUD Operations guide.

Important

Primary Key Field Name Must Be _id

MongoDB requires the primary key field to map to the _id field. You can explicitly set the @Id field's column name by using a @Column annotation or an orm.xml override. If you set this name to anything other than _id, the Hibernate ORM extension throws a FeatureNotSupportedException at bootstrap. To resolve this error, remove the @Column annotation or set its name to _id.

This validation does not apply to legacy Hibernate Mapping (HBM) XML mappings. If you map your entity by using HBM XML, the Hibernate ORM extension silently renames the identifier column to _id instead of throwing an exception.

The @Table annotation accepts an optional schema element that prefixes your collection name. When you set both elements, the Hibernate ORM extension maps the entity to a collection named <schema name>.<collection name>.

A schema qualifier changes only the collection's name. A schema is not a separate MongoDB database. Every schema-qualified collection resides in the database that your SessionFactory instance connects to. Because these collections share one database, a transaction can span multiple schemas.

Use the following syntax to apply a schema qualifier:

@Entity
@Table(schema = "<schema name>", name = "<collection name>")
public class <EntityName> {
// Define your fields, constructors, and methods here
}

Note

Schema Qualifier Limitations

The Hibernate ORM extension rejects the catalog element of the @Table annotation and the hibernate.default_catalog configuration property at bootstrap. If your application must access multiple MongoDB databases, create a separate SessionFactory instance for each database.

The Hibernate ORM extension rejects a dot (.) in a table name or a schema name at bootstrap. This restriction applies to primary, secondary, join, and collection table names, and to schema names set by either the schema attribute or the hibernate.default_schema configuration property.

This sample Movie.java entity class defines a Movie entity that includes the following information:

  • @Entity annotation that marks the class as a Hibernate ORM entity

  • @Table annotation that maps the entity to the movies collection from the Atlas sample datasets

  • @Id and @ObjectIdGenerator annotations that designate the id field as the primary key and configure automatic ObjectId generation

    Tip

    Primary Key Values

    This example specifies the ObjectId field as the entity's primary key, but you can also set String or int fields as the primary key by using the @Id annotation. You cannot use a java.util.UUID field as the primary key. To learn more, see Unsupported Field Types.

  • Private fields that represent movie data

  • Default and parameterized constructors for entity instantiation

  • Getter and setter methods that provide access to the entity's fields

package org.example;
import com.mongodb.hibernate.annotations.ObjectIdGenerator;
import org.bson.types.ObjectId;
import java.util.List;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table(name = "movies")
public class Movie {
@Id
@ObjectIdGenerator
private ObjectId id;
private String title;
private String plot;
private int year;
private List<String> cast;
private List<String> directors;
public Movie(String title, String plot, int year, List<String> cast, List<String> directors) {
this.title = title;
this.plot = plot;
this.year = year;
this.cast = cast;
this.directors = directors;
}
public Movie() {
}
public ObjectId getId() {
return id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPlot() {
return plot;
}
public void setPlot(String plot) {
this.plot = plot;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public List<String> getCast() {
return cast;
}
public void setCast(List<String> cast) {
this.cast = cast;
}
public List<String> getDirectors() {
return directors;
}
public void setDirectors(List<String> directors) {
this.directors = directors;
}
}

Tip

To learn more about the fields used in the entity class definition, see the MongoDB BSON Fields section of this guide.

To key an entity on more than one field, define a composite primary key. Create a plain @Embeddable class or record that holds the key components. Then, annotate your entity's identifier field with the @jakarta.persistence.EmbeddedId annotation.

The following BookId embeddable defines a key that consists of a publisherId component and a bookNo component:

@Embeddable
public record BookId(long publisherId, long bookNo) {}

The following Book entity uses BookId as its primary key:

@Entity(name = "Book")
@Table(name = "books")
public class Book {
@EmbeddedId
private BookId id;
private String title;
public Book() {
}
public Book(BookId id, String title) {
this.id = id;
this.title = title;
}
// Getter and setter methods
}

You must assign composite key values in your application before you persist an entity. The Hibernate ORM extension does not generate composite key values.

The Hibernate ORM extension stores a composite key as an _id sub-document. The preceding Book entity produces documents in the following format:

{
"_id": { "bookNo": 2, "publisherId": 10 },
"title": "My Book"
}

The Hibernate ORM extension orders the components of the _id sub-document alphabetically by component name, rather than in the order that you declare them. This order is the same whether you declare the embeddable as a class or as a record.

Important

Component Order Affects Document Matching

MongoDB compares sub-documents by field order, so two _id values that contain the same components in a different order do not match. Because the Hibernate ORM extension always writes components in the same order, this behavior affects you only if you also read or write these documents outside of the Hibernate ORM extension, such as through the MongoDB Java driver.

The Hibernate ORM extension throws a FeatureNotSupportedException when your application starts if you declare a composite key in any of the following ways:

  • A non-aggregated identifier, declared either with the @jakarta.persistence.IdClass annotation or with multiple @Id attributes. Declare the key with @EmbeddedId instead.

  • A @Struct aggregate embeddable as the identifier. Use a plain @Embeddable instead.

  • A component that is not a basic value, such as a nested @Embeddable or a collection. Every component of a composite key must be a basic value.

  • An association within the identifier, including derived identity that uses the @jakarta.persistence.MapsId annotation.

You also cannot compare a whole composite identifier by using an ordering operator such as > or <. Compare individual components instead.

The Hibernate ORM extension supports embedded documents through Hibernate ORM @Embeddable annotations. With embedded documents, you can create One-to-Many, Many-to-One, and One-to-One relationships within MongoDB documents. This format is ideal for representing data that is frequently accessed together.

To represent embedded documents, use the @Struct and @Embeddable annotations on a class to create a @Struct aggregate embeddable. Then, include the embeddable type in your parent entity as a field. The Hibernate ORM extension supports embedding single objects, arrays, and collections of embeddables.

Tip

To learn more about @Struct aggregate embeddables, see @Struct aggregate embeddable mapping in the Hibernate ORM documentation.

A One-to-One relationship is when a record in one database is associated with exactly one record in another database. In MongoDB, you can create a collection with an embedded document field to model a One-to-One relationship. The Hibernate ORM extension allows you to create embedded document fields by using @Struct aggregate embeddables.

The example defines a field with a @Struct aggregate embeddable type in an entity similar to the Define an Entity example in this guide. The sample Movie.java entity class includes the following information:

  • @Entity and @Table annotations that define the entity and map it to the movies collection

  • @Id and @ObjectIdGenerator annotations that designate the id field as the primary key

  • String field that represents the movie's title

  • @Struct aggregate embeddable fields that represent movie awards and studio information

The following example represents a One-to-One relationship because each Movie entity is associated with one Awards embeddable and one Studio embeddable:

@Entity
@Table(name = "movies")
public class Movie {
@Id
@ObjectIdGenerator
private ObjectId id;
private String title;
private Awards awards;
private Studio studio;
public Movie(String title, Awards awards, Studio studio) {
this.title = title;
this.awards = awards;
this.studio = studio;
}
public Movie() {
}
// Getter and setter methods
}

The following sample code creates an Awards @Struct aggregate embeddable:

@Embeddable
@Struct(name = "Awards")
public class Awards {
private int wins;
private int nominations;
private String text;
public Awards(int wins, int nominations, String text) {
this.wins = wins;
this.nominations = nominations;
this.text = text;
}
public Awards() {
}
// Getter and setter methods
}

The following sample code creates a Studio @Struct aggregate embeddable:

@Embeddable
@Struct(name = "Studio")
public class Studio {
private String name;
private String location;
private int foundedYear;
public Studio(String name, String location, int foundedYear) {
this.name = name;
this.location = location;
this.foundedYear = foundedYear;
}
public Studio() {
}
// Getter and setter methods
}

A One-to-Many relationship is when a record in one database is associated with many records in another database. In MongoDB, you can define a collection field that stores a list of embedded documents to model a One-to-Many relationship. The Hibernate ORM extension allows you to create embedded document fields by using a list of @Struct aggregate embeddables.

The example defines a field that stores a list of @Struct aggregate embeddables in an entity similar to the Define an Entity Example in this guide. The sample Movie.java entity class includes the following information:

  • @Entity and @Table annotations that define the entity and map it to the movies collection

  • @Id and @ObjectIdGenerator annotations that designate the id field as the primary key

  • String field that represents the movie's title

  • List field that stores multiple Writer @Struct aggregate embeddables, which represents writer information

The following example represents a One-to-Many relationship because each Movie entity is associated with multiple Writer embeddables:

@Entity
@Table(name = "movies")
public class Movie {
@Id
@ObjectIdGenerator
@Column(name = "_id")
private ObjectId id;
private String title;
private List<Writer> writers;
public Movie(String title, List<Writer> writers) {
this.title = title;
this.writers = writers;
}
public Movie() {
}
// Getter and setter methods
}

The following sample code creates a Writer @Struct aggregate embeddable:

@Embeddable
@Struct(name = "Writer")
public class Writer {
private String name;
public Writer() {
}
public Writer(String name) {
this.name = name;
}
// Getter and setter methods
}

You can nest a flattened embeddable inside a @Struct aggregate embeddable. A flattened embeddable is a class that includes an @Embeddable annotation but not a @Struct annotation. The Hibernate ORM extension stores the fields of a flattened embeddable as fields of the parent embedded document instead of as a separate nested document.

The following sample code creates a Studio @Struct aggregate embeddable that includes an Address flattened embeddable as a field:

@Embeddable
@Struct(name = "Studio")
public class Studio {
private String name;
private Address address;
public Studio() {
}
public Studio(String name, Address address) {
this.name = name;
this.address = address;
}
// Getter and setter methods
}

The following sample code creates the Address flattened embeddable. The class omits the @Struct annotation:

@Embeddable
public class Address {
private String city;
private String country;
public Address() {
}
public Address(String city, String country) {
this.city = city;
this.country = country;
}
// Getter and setter methods
}

When you persist an entity that includes a Studio field, the Address fields become fields of the Studio field's embedded document. The following example document has a Studio field named studio that stores the fields of its Address flattened embeddable:

{
"_id": { "$oid": "..." },
"title": "Breathless",
"studio": {
"name": "Les Films Impéria",
"city": "Paris",
"country": "France"
}
}

To learn how to map a class hierarchy to a MongoDB collection, see the Map an Entity Inheritance Hierarchy guide.

To learn how to use your entities to run database operations, see the following guides in the Interact with Data section:

To learn more about Hibernate ORM fields, see the Mapping types section in the Hibernate ORM documentation.

To learn more about Hibernate ORM entities, see POJO Models in the Hibernate ORM documentation.