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

Perform CRUD Operations

In this guide, you can learn how to use the MongoDB Extension for Hibernate ORM to run create, read, update, and delete (CRUD) operations on your MongoDB collections.

The examples in this guide use the Movie entity, which represents the sample_mflix.movies collection from the Atlas sample datasets. The Movie entity has the following definition:

import com.mongodb.hibernate.annotations.ObjectIdGenerator;
import org.bson.types.ObjectId;
import java.time.Instant;
import java.util.List;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
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;
private Instant released;
@Embedded
private Awards awards;
@OneToMany(mappedBy = "movie", fetch = FetchType.LAZY)
private List<Comment> comments;
public Movie(String title, String plot, int year, List<String> cast, List<String> directors, Instant released, Awards awards) {
this.title = title;
this.plot = plot;
this.year = year;
this.cast = cast;
this.directors = directors;
this.released = released;
this.awards = awards;
}
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;
}
public Awards getAwards() {
return awards;
}
public void setAwards(Awards awards) {
this.awards = awards;
}
public Instant getReleased() {
return released;
}
public void setReleased(Instant released) {
this.released = released;
}
public List<Comment> getComments() {
return comments;
}
public void setComments(List<Comment> comments) {
this.comments = comments;
}
}

To learn how to create a Java application that uses the MongoDB Extension for Hibernate ORM to interact with this MongoDB sample collection, see the Get Started tutorial.

Important

Persistence Contexts

To enable Hibernate ORM to interact with the database, you must run operations inside a persistence context by using a Hibernate Session or a Jakarta Persistence EntityManager. You also must run write operations inside a transaction to modify MongoDB data and maintain data integrity.

Before running the examples in this guide, ensure that you add persistence context and transaction management code to your application that resembles the following code:

var sf = HibernateUtil.getSessionFactory();
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
// ... Perform CRUD operations here
tx.commit();
session.close();
sf.close();

To use a session, you must create a HibernateUtil.java file that configures a SessionFactory. To learn more, see the Configure your Application step of the Get Started tutorial.

// Replace <persistence unit> with the name of your persistence unit in the persistence.xml file
EntityManagerFactory emf = Persistence.createEntityManagerFactory("<persistence unit>");
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
// ... Perform CRUD operations here
entityManager.getTransaction().commit();
entityManager.close();
emf.close;

To use an EntityManager, you must create a persistence.xml file that declares a persistence unit. To learn more, see the Tutorial using JPA-standard APIs in the Hibernate ORM documentation.

Create a document by passing an entity instance to to the following methods, which insert the corresponding document into your collection:

  • org.hibernate.Session.persist(): Use the Hibernate API to apply your changes to the database

  • jakarta.persistence.EntityManager.persist(): Use the Jakarta Persistence API to apply your changes to the database

Tip

To learn more about creating entity instances and persisting them to your database, see Making entities persistent in the Hibernate ORM user guide.

The following example creates a new Movie entity instance and uses the persist() method to insert a corresponding document into the sample_mflix.movies collection:

var myMovie = new Movie();
myMovie.setTitle("Knives Out");
myMovie.setYear(2019);
myMovie.setCast(List.of("Ana de Armas", "Daniel Craig", "Chris Evans"));
myMovie.setPlot("Detective Benoit Blanc investigates the mysterious death of crime novelist Harlan Thrombey, " +
"unraveling lies as every Thrombey family member becomes a suspect.");
session.persist(myMovie);
var myMovie = new Movie();
myMovie.setTitle("Knives Out");
myMovie.setYear(2019);
myMovie.setCast(List.of("Ana de Armas", "Daniel Craig", "Chris Evans"));
myMovie.setPlot("Detective Benoit Blanc investigates the mysterious death of crime novelist Harlan Thrombey, " +
"unraveling lies as every Thrombey family member becomes a suspect.");
entityManager.persist(myMovie);

To retrieve documents from your collection, pass your query criteria to the createQuery() method. The following APIs both provide the createQuery() method:

  • Hibernate's Session API: Use Hibernate Query Language (HQL) syntax to define your queries

  • Jakarta Persistence's EntityManager API: Use Jakarta Persistence Query Language (JPQL) syntax, a subset of HQL, to define your queries

Tip

To learn more about retrieving data by using HQL and JPQL syntax, see Select statements in the Hibernate ORM query guide.

Note

This section describes how to read documents by using HQL and JPQL, but you can also use the criteria builder or native queries to retrieve data. To learn more, see the following guides:

To retrieve only one document that matches your query criteria, chain the getSingleResult() method to the createQuery() method. The following example retrieves one document that has a title value of "Boyhood" from the sample_mflix.movies collection:

var singleResult = session.createQuery("from Movie where title = :t", Movie.class)
.setParameter("t", "Boyhood")
.getSingleResult();
System.out.println("Title: " + singleResult.getTitle() + ", Year: " + singleResult.getYear());
var singleResult = entityManager.createQuery("select m from Movie m where m.title = :t", Movie.class)
.setParameter("t", "Boyhood")
.getSingleResult();
System.out.println("Title: " + singleResult.getTitle() + ", Year: " + singleResult.getYear());

Tip

Query Syntax

To learn more about HQL and JPQL syntax, see A Guide to Hibernate Query Language in the Hibernate ORM documentation.

The following example calls the createQuery() method on a session to retrieve documents from the sample_mflix.movies collection. The code uses HQL and JPQL to return documents that have a year value of 1920 and prints their title values:

var results = session.createQuery("from Movie where year = :y", Movie.class)
.setParameter("y", 1920)
.getResultList();
results.forEach(movie -> System.out.println(movie.getTitle()));
var results = entityManager.createQuery("select m from Movie m where m.year = :y", Movie.class)
.setParameter("y", 1920)
.getResultList();
results.forEach(movie -> System.out.println(movie.getTitle()));

You can perform the following operations to modify documents in a collection:

  • Update one document: Call your entity's setter methods to change field values of one entity instance, and then use a session or entity manager to persist your changes.

  • Update multiple documents: Pass an update statement to the createQuery() or createMutationQuery() methods on a session or entity manager. Then, call the executeUpdate() method to apply your changes to the database.

Tip

To learn more about modifying data by using Hibernate ORM, see the following resources:

The following example retrieves a document by its ObjectId value. Then, the example calls the Movie entity's setTitle() method to update the document's title value to "Jurassic Park I":

// Your ObjectId value might differ
Movie movieById = session.get(Movie.class, new ObjectId("573a1399f29313caabcedc5d"));
movieById.setTitle("Jurassic Park I");
session.persist(movieById);
// Your ObjectId value might differ
Movie movieById = entityManager.find(Movie.class, new ObjectId("573a1399f29313caabcedc5d"));
movieById.setTitle("Jurassic Park I");
entityManager.persist(movieById);

The following example updates the title value of matching documents from "The Three Stooges" to "The 3 Stooges". Then, the example calls the executeUpdate() method to apply the changes to the database:

var updateResult = session.createMutationQuery(
"update Movie set title = :new where title = :old")
.setParameter("new", "The 3 Stooges")
.setParameter("old", "The Three Stooges")
.executeUpdate();
System.out.println("Number of movies updated: " + updateResult);
var updateResult = entityManager.createQuery(
"update Movie m set m.title = :new where m.title = :old")
.setParameter("new", "The 3 Stooges")
.setParameter("old", "The Three Stooges")
.executeUpdate();
System.out.println("Number of movies updated: " + updateResult);

The SET clause of a bulk update statement can also use an expression instead of a literal value. The expression can reference the field being updated or another field on the entity.

The following example uses an arithmetic expression to increment the year value of documents that have a title value of "The 3 Stooges":

var updateResult = session.createMutationQuery(
"update Movie m set m.year = m.year + 1 where m.title = :title")
.setParameter("title", "The 3 Stooges")
.executeUpdate();
System.out.println("Number of movies updated: " + updateResult);

The following example uses a field reference to set the plot value to match the title value for documents that have a year value of 1920:

var updateResult = session.createMutationQuery(
"update Movie m set m.plot = m.title where m.year = :year")
.setParameter("year", 1920)
.executeUpdate();
System.out.println("Number of movies updated: " + updateResult);

An upsert operation updates a document if a matching document exists, or inserts a new document if no match exists. To perform an upsert, use the upsert() or upsertMultiple() method. These methods are available only on Hibernate's StatelessSession API.

Note

A StatelessSession instance does not track changes to the entities it retrieves. To save changes to an entity, pass it to another write method. Use StatelessSession for bulk write workflows.

The Hibernate ORM extension creates the filter for an upsert operation from your entity's identifier, so your application must assign the identifier value before you call upsert().

The upsert() method does not generate identifier values, even if your entity uses the @ObjectIdGenerator annotation. If you do not assign an identifier value, the Hibernate ORM extension stores the document with a null _id value.

You can use the @Column(updatable = false)` annotation to protect a field from updates during an upsert operation. The following Movie entity definition annotates the released field with @Column(updatable = false), which instructs the Hibernate ORM extension to write to the field when it inserts a document but to omit the field when it updates an existing document:

@Entity
@Table(name = "movies")
public class Movie {
@Id
@ObjectIdGenerator
private ObjectId id;
private String title;
private int year;
@Column(updatable = false)
private Instant released;
// Getters and setters omitted
}

The Hibernate ORM extension sends fields that are both insertable and updatable in the $set operator of the generated update statement. It sends insertable-only fields, such as fields annotated with @Column(updatable = false), in the $setOnInsert operator.

The following example creates a Movie entity instance and passes it to the upsert() method. If a document that has the specified ObjectId value exists, the Hibernate ORM extension updates the title and year values of that document. Otherwise, the Hibernate ORM extension inserts a new document:

try (StatelessSession statelessSession = sf.openStatelessSession()) {
var movie = new Movie();
movie.setId(new ObjectId("573a1398f29313caabce9682"));
movie.setTitle("The General");
movie.setYear(1926);
movie.setReleased(Instant.parse("1927-02-24T00:00:00Z"));
statelessSession.upsert(movie);
}

To upsert several entity instances in one operation, pass a list of instances to the upsertMultiple() method. The following example upserts two Movie entity instances:

try (StatelessSession statelessSession = sf.openStatelessSession()) {
var firstMovie = new Movie();
firstMovie.setId(new ObjectId("573a1398f29313caabce9682"));
firstMovie.setTitle("The General");
firstMovie.setYear(1926);
var secondMovie = new Movie();
secondMovie.setId(new ObjectId("573a1398f29313caabce9683"));
secondMovie.setTitle("Metropolis");
secondMovie.setYear(1927);
statelessSession.upsertMultiple(List.of(firstMovie, secondMovie));
}

The following entity mappings are unsupported in upsert operations. When you upsert an entity that uses one of these mappings, the Hibernate ORM extension throws a FeatureNotSupportedException:

  • Entities that have a field annotated with @Version.

  • Entities that have a field annotated with @Column(insertable = false). MongoDB Query Language provides no way to write a field only when an operation matches an existing document.

  • Entities whose only persistent attribute is the identifier. An upsert on this type of entity has no fields to update, so the Hibernate ORM extension rejects the operation.

You can perform the following operations to delete documents from a collection:

  • Delete one document: Call the remove() method on a session or entity manager, passing the entity instance that you want to delete as an argument.

  • Delete multiple documents: Pass a delete statement to the createQuery() or createMutationQuery() methods on a session or entity manager. Then, call the executeUpdate() method to apply your changes to the database.

Tip

To learn more about deleting data by using Hibernate ORM, see the following resources:

The following example retrieves a document by its ObjectId value. Then, the example calls the remove() method on a session to delete the corresponding document from the sample_mflix.movies collection:

// Your ObjectId value might differ
Movie movieToDelete = session.get(Movie.class, new ObjectId("573a1399f29313caabcedc5d"));
session.remove(movieToDelete);
// Your ObjectId value might differ
Movie movieToDelete = entityManager.find(Movie.class, new ObjectId("573a1399f29313caabcedc5d"));
entityManager.remove(movieToDelete);

The following example deletes all documents that have a year value of 1920 from the sample_mflix.movies collection. The example passes a delete statement to the createMutationQuery() method, and then calls the executeUpdate() method to apply the changes to the database:

var deleteResult = session.createMutationQuery(
"delete Movie where year = :y")
.setParameter("y", 1920)
.executeUpdate();
System.out.println("Number of movies deleted: " + deleteResult);
var deleteResult = entityManager.createQuery(
"delete Movie m where m.year = :y")
.setParameter("y", 1920)
.executeUpdate();
System.out.println("Number of movies deleted: " + deleteResult);

To learn more about performing CRUD operations by using the Hibernate ORM, see the following resources:

To view more create, read, update, and delete examples, see the following sections of the Get Started tutorial:

To learn more about using the Hibernate ORM extension to run queries, see the following guides: