Docs Menu
Docs Home
/ /

Specify a Query

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.

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;
@Entity
@Table(name = "movies")
public class Movie {
@Id
@ObjectIdGenerator
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.

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:

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?
...

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

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.

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:

  1. Create a CriteriaBuilder object from a session or an entity manager.

  2. Create a CriteriaQuery object from the builder and specify the entity to query.

  3. Use query methods provided by the CriteriaQuery class 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

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.

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.

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
...

You can use the following operators in your query statements to combine multiple query criteria:

  • and: Match all criteria

  • or: Match any criteria

  • not: 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

This section describes how to modify your query results in the following ways:

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

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

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();

This section describes how to run queries on the following fields:

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"));

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

The Hibernate ORM extension supports the following functions for querying array fields:

  • array_contains(): Match documents where an array field contains a specified value

  • array_contains_nullable(): Match documents where an array field contains a specified value, including null values

  • array_includes(): Match documents where an array field includes another array value

  • array_includes_nullable(): Match documents where an array field includes another array value, including null values

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

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.

Back

CRUD Operations

On this page