Overview
In this guide, you can learn how to use the MongoDB Extension for Hibernate ORM to specify a database query.
You can refine the set of documents that a query returns by creating a query filter. A query filter is an expression that specifies the search criteria MongoDB uses to match documents in a read or write operation. To create MongoDB query filters, use Hibernate Query Language (HQL) or Jakarta Persistence Query Language (JPQL) statements.
Tip
To learn more about HQL and JPQL syntax, see A Guide to Hibernate Query Language in the Hibernate ORM documentation.
Note
Query Support
The MongoDB Extension for Hibernate ORM does not support all MongoDB and Hibernate query features. To learn more, see Query Support on the Feature Compatibility page.
Sample Data
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 jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.Table; public class Movie { private ObjectId id; private String title; private String plot; private int year; private String[] cast; public Movie(String title, String plot, int year, String[] cast) { this.title = title; this.plot = plot; this.year = year; this.cast = cast; } 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 String[] getCast() { return cast; } public void setCast(String[] cast) { this.cast = cast; } }
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. Use HQL to define session queries, and use JPQL to define entity manager queries.
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.
Run a Query
To query your MongoDB data, call the createQuery() method on a
session or an entity manager. Then, specify your matching criteria in a
Hibernate Query Language (HQL) or Jakarta Persistence Query Language
(JPQL) statement.
This section describes how to perform the following query operations:
Retrieve All Documents
To retrieve all documents from a collection, pass a basic select statement
to the createQuery() method. In this statement, specify the entity
that represents the collection you want to query.
The following example retrieves the title values of all documents from the sample_mflix.movies
collection by querying the Movie entity:
var allDocs = session.createQuery("select title from Movie", String.class) .getResultList(); for (var t : allDocs) { System.out.println("Title: " + t); }
Title: A Corner in Wheat Title: Gertie the Dinosaur Title: The Perils of Pauline Title: Civilization Title: Where Are My Children? ...
var allDocs = entityManager.createQuery("select m.title from Movie m", String.class) .getResultList(); for (var t : allDocs) { System.out.println("Title: " + t); }
Title: A Corner in Wheat Title: Gertie the Dinosaur Title: The Perils of Pauline Title: Civilization Title: Where Are My Children? ...
Retrieve Matching Documents
To retrieve documents that match specific criteria, pass a select statement
with a where clause to the createQuery() method. In this statement,
specify the entity that represents the collection you want to query and
the matching criteria.
The following example retrieves documents that have a title value
of "Romeo and Juliet" from the sample_mflix.movies collection:
var matchingDocs = session.createQuery("from Movie where title = :t", Movie.class) .setParameter("t", "Romeo and Juliet") .getResultList(); for (var m : matchingDocs) { System.out.println("Title: " + m.getTitle() + ", Year: " + m.getYear()); }
Title: Romeo and Juliet, Year: 1936 Title: Romeo and Juliet, Year: 1968
var matchingDocs = entityManager.createQuery("select m from Movie m where m.title = :t", Movie.class) .setParameter("t", "Romeo and Juliet") .getResultList(); for (var m : matchingDocs) { System.out.println("Title: " + m.getTitle() + ", Year: " + m.getYear()); }
Title: Romeo and Juliet, Year: 1936 Title: Romeo and Juliet, Year: 1968
Retrieve One Document
To retrieve a single document that matches specific criteria, chain the
getSingleResult() method to the createQuery() method.
The following example retrieves a single document that has a title value
of "Best in Show" from the sample_mflix.movies collection:
var singleResult = session.createQuery("from Movie where title = :t", Movie.class) .setParameter("t", "Best in Show") .getSingleResult(); System.out.println("Title: " + singleResult.getTitle() + ", Year: " + singleResult.getYear());
Title: Best in Show, Year: 2000
var singleResult = entityManager.createQuery("select m from Movie m where m.title = :t", Movie.class) .setParameter("t", "Best in Show") .getSingleResult(); System.out.println("Title: " + singleResult.getTitle() + ", Year: " + singleResult.getYear());
Title: Best in Show, Year: 2000
Important
NonUniqueResultException Errors
If your query matches multiple documents, the getSingleResult() method
throws a NonUniqueResultException error. To avoid this error, ensure that
your query matches only one document or limit your query results to
one document.
Run Criteria API Queries
Instead of using HQL or JPQL statements to create query filters, you can use the Jakarta Persistence Criteria API to build type-safe queries programmatically.
To create a query by using the Criteria API, perform the following actions:
Create a
CriteriaBuilderobject from a session or an entity manager.Create a
CriteriaQueryobject from the builder and specify the entity to query.Use query methods provided by the
CriteriaQueryclass to specify your query criteria.
Tip
To learn more about the Criteria API, see Using the Criteria API to Create Queries in the Jakarta EE documentation.
The following example uses the Criteria API to retrieve all documents
that have a year value of 1925 from the sample_mflix.movies
collection:
CriteriaBuilder cb = session.getCriteriaBuilder(); CriteriaQuery<Movie> cq = cb.createQuery(Movie.class); Root<Movie> movieRoot = cq.from(Movie.class); cq.select(movieRoot).where(cb.equal(movieRoot.get("year"), 1925)); session.createQuery(cq).getResultList() .forEach(m -> System.out.println(m.getTitle()));
Lady Windermere's Fan Clash of the Wolves Grass: A Nation's Battle for Life
CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<Movie> cq = cb.createQuery(Movie.class); Root<Movie> movieRoot = cq.from(Movie.class); cq.select(movieRoot).where(cb.equal(movieRoot.get("year"), 1925)); entityManager.createQuery(cq).getResultList() .forEach(m -> System.out.println(m.getTitle()));
Lady Windermere's Fan Clash of the Wolves Grass: A Nation's Battle for Life
Run Native Queries
To run MongoDB queries that are not currently supported by the Hibernate ORM extension,
you can pass your query as a MongoDB Query Language (MQL) statement to the
createNativeQuery() method.
To learn how to run native queries, see the Perform Native Queries guide.
Customize Your Query Filter
This section describes how to use operators to create the following types of query filters:
Tip
This section does not describe all available query operators. To view a complete list of query operators, see Operator expressions in the Hibernate ORM query guide.
Use Comparison Filters
Note
The Hibernate ORM extension does not support all comparison operators, including
LIKE and BETWEEN. To learn more about support limitations, see
Query Support on the Feature Compatibility
page.
You can use the following operators in your query statements to compare field values to specified query values:
=: Equality matching<>: Inequality matching>: Greater than comparisons>=: Greater than or equal comparisons<: Less than comparisons<=: Less than or equal comparisons
The following example retrieves documents that have a year value
greater than or equal to 2015 from the sample_mflix.movies
collection:
var comparisonResult = session.createQuery("from Movie where year >= :y", Movie.class) .setParameter("y", 2015) .getResultList(); for (var m : comparisonResult) { System.out.println("Title: " + m.getTitle()); }
Title: Jurassic World Title: The Stanford Prison Experiment Title: Ex Machina Title: Ant-Man Title: The Danish Girl Title: The Wedding Ringer Title: Good Ol' Boy Title: A Tale of Love and Darkness Title: Aloha ...
var comparisonResult = entityManager.createQuery("select m from Movie m where m.year >= :y", Movie.class) .setParameter("y", 2015) .getResultList(); for (var m : comparisonResult) { System.out.println("Title: " + m.getTitle()); }
Title: Jurassic World Title: The Stanford Prison Experiment Title: Ex Machina Title: Ant-Man Title: The Danish Girl Title: The Wedding Ringer Title: Good Ol' Boy Title: A Tale of Love and Darkness Title: Aloha ...
Use Logical Filters
You can use the following operators in your query statements to combine multiple query criteria:
and: Match all criteriaor: Match any criterianot: Invert criteria
The following example retrieves a document that has a title value
of "The Godfather" and a year value of 1972 from the
sample_mflix.movies collection:
var logicalResult = session.createQuery("from Movie where title = :t and year = :y", Movie.class) .setParameter("t", "The Godfather") .setParameter("y", 1972) .getSingleResult(); System.out.println("Title: " + logicalResult.getTitle());
Title: The Godfather
var logicalResult = entityManager.createQuery("select m from Movie m where m.title = :t and m.year = :y", Movie.class) .setParameter("t", "The Godfather") .setParameter("y", 1972) .getSingleResult(); System.out.println("Title: " + logicalResult.getTitle());
Title: The Godfather
Modify Query Results
This section describes how to modify your query results in the following ways:
Sort Results
You can sort query results by the value of a specified field
by using the order by clause in your query statement. By default,
the order by clause sorts documents in ascending order. To sort
documents in descending order, append the desc keyword to the field name.
The following example retrieves matching documents from the sample_mflix.movies
collection and sorts them by the year field in descending order:
var sortResult = session.createQuery("from Movie where title = :t order by year desc", Movie.class) .setParameter("t", "Cinderella") .getResultList(); for (var m : sortResult) { System.out.println("Title: " + m.getTitle() + ", Year: " + m.getYear()); }
Title: Cinderella, Year: 2015 Title: Cinderella, Year: 1997 Title: Cinderella, Year: 1950
var sortResult = entityManager.createQuery("select m from Movie m where m.title = :t order by m.year desc", Movie.class) .setParameter("t", "Cinderella") .getResultList(); for (var m : sortResult) { System.out.println("Title: " + m.getTitle() + ", Year: " + m.getYear()); }
Title: Cinderella, Year: 2015 Title: Cinderella, Year: 1997 Title: Cinderella, Year: 1950
Skip Results
You can skip a specified number of documents in your query results
by chaining the setFirstResult() method to the query. Pass the number
of initial documents to skip as an argument to this method.
The following example runs the same query as the preceding example but skips the first matching document in the results:
var skipResult = session.createQuery("from Movie where title = :t order by year desc", Movie.class) .setParameter("t", "Cinderella") .setFirstResult(1) .getResultList(); for (var m : skipResult) { System.out.println("Title: " + m.getTitle() + ", Year: " + m.getYear()); }
Title: Cinderella, Year: 1997 Title: Cinderella, Year: 1950
var skipResult = entityManager.createQuery("select m from Movie m where m.title = :t order by m.year desc", Movie.class) .setParameter("t", "Cinderella") .setFirstResult(1) .getResultList(); for (var m : skipResult) { System.out.println("Title: " + m.getTitle() + ", Year: " + m.getYear()); }
Title: Cinderella, Year: 1997 Title: Cinderella, Year: 1950
Limit Results
You can limit the number of documents that your query returns
by chaining the setMaxResults() method to the query. Pass the maximum
number of documents to return as an argument to this method.
The following example runs the same query as the sort example but returns up to two matching documents in the results:
var limitResult = session.createQuery("from Movie where title = :t order by year desc", Movie.class) .setParameter("t", "Cinderella") .setMaxResults(2) .getResultList(); for (var m : limitResult) { System.out.println("Title: " + m.getTitle() + ", Year: " + m.getYear()); }
Title: Cinderella, Year: 2015 Title: Cinderella, Year: 1997
var limitResult = entityManager.createQuery("select m from Movie m where m.title = :t order by m.year desc", Movie.class) .setParameter("t", "Cinderella") .setMaxResults(2) .getResultList(); for (var m : limitResult) { System.out.println("Title: " + m.getTitle() + ", Year: " + m.getYear()); }
Title: Cinderella, Year: 2015 Title: Cinderella, Year: 1997
Alternatively, you can use a limit clause in your HQL or JPQL statement
to restrict the number of documents that your query returns, as shown
in the following code:
var limitClauseResult = session.createQuery("from Movie where title = :t order by year desc limit 2", Movie.class) .setParameter("t", "Cinderella") .getResultList();
var limitClauseResult = entityManager.createQuery("select m from Movie m where m.title = :t order by m.year desc limit 2", Movie.class) .setParameter("t", "Cinderella") .getResultList();
Advanced Field Queries
This section describes how to run queries on the following fields:
Query a Primary Key Field
To retrieve a document based on its ObjectId value, you can
pass this value as an argument to the get() method, if you're
using a session, or the find() method, if you're using an entity manager.
The following example retrieves a document from the sample_mflix.movies
collection by its ObjectId value:
var movieById = session.get(Movie.class, new ObjectId("573a13a8f29313caabd1d53c"));
var movieById = entityManager.find(Movie.class, new ObjectId("573a13a8f29313caabd1d53c"));
Query an Embedded Field
You can represent MongoDB embedded documents by creating
@Struct aggregate embeddables. You cannot
create query filters on individual embeddable values, but you can
use the Hibernate ORM extension to fetch @Struct aggregate embeddables
associated with specific parent entities.
Tip
To learn more about representing embedded documents, see Embedded Data in the Create Entities guide.
Important
Query Limitations
To learn more about the query limitations for embeddables, see Hibernate Query Support on the Feature Compatibility page.
The following example retrieves documents that have a title value
of "Hairspray" from the sample_mflix.movies collection. Then,
the code fetches the awards field, which stores the Awards @Struct
aggregate embeddable, and prints the wins field of the Awards embeddable type:
var embeddedResult = session.createQuery("select awards from Movie where title = :title", Awards.class) .setParameter("title", "Hairspray") .getResultList(); for (var a : embeddedResult) { System.out.println("Award wins: " + a.getWins()); }
Award wins: 0 Award wins: 21
var embeddedResult = entityManager.createQuery("select m.awards from Movie m where m.title = :title", Awards.class) .setParameter("title", "Hairspray") .getResultList(); for (var a : embeddedResult) { System.out.println("Award wins: " + a.getWins()); }
Award wins: 0 Award wins: 21
Query an Array Field
The Hibernate ORM extension supports the following functions for querying array fields:
array_contains(): Match documents where an array field contains a specified valuearray_contains_nullable(): Match documents where an array field contains a specified value, includingnullvaluesarray_includes(): Match documents where an array field includes another array valuearray_includes_nullable(): Match documents where an array field includes another array value, includingnullvalues
Tip
To learn more about array functions, see Functions for dealing with arrays in the Hibernate ORM user guide.
The following example uses the array_contains() function to retrieve
documents that have the value "Kathryn Hahn" in the cast array field
from the sample_mflix.movies collection:
var arrayResult = session.createQuery("from Movie where array_contains(cast, :actor)", Movie.class) .setParameter("actor", "Kathryn Hahn") .getResultList(); for (var m : arrayResult) { System.out.println("Title: " + m.getTitle()); }
Title: How to Lose a Guy in 10 Days Title: The Secret Life of Walter Mitty Title: Bad Words Title: Afternoon Delight Title: The D Train
var arrayResult = entityManager.createQuery("select m from Movie m where array_contains(m.cast, :actor)", Movie.class) .setParameter("actor", "Kathryn Hahn") .getResultList(); for (var m : arrayResult) { System.out.println("Title: " + m.getTitle()); }
Title: How to Lose a Guy in 10 Days Title: The Secret Life of Walter Mitty Title: Bad Words Title: Afternoon Delight Title: The D Train
Additional Information
To learn more about performing other operations on your MongoDB data, see the Perform CRUD Operations guide.
To learn more about using HQL and JPQL to run queries, see A Guide to Hibernate Query Language in the Hibernate ORM documentation.