Docs Menu
Docs Home
/ /

Perform Native Database Queries

In this guide, you can learn how to use the MongoDB Extension for Hibernate ORM to run native queries on your MongoDB database. Instead of Hibernate Query Language (HQL) or Jakarta Persistence Query Language (JPQL), native queries allow you to use MongoDB Query Language (MQL) to specify your query. MQL is a query syntax designed for interacting with MongoDB's document-based model.

Tip

MongoDB Query Language

To learn more about MQL's syntax and functionality, see MongoDB Query Language Reference in the MongoDB Server manual.

Hibernate ORM's createQuery() method does not support some MongoDB query features. The createNativeQuery() method allows you to specify database queries in MQL and bypass some operational limitations of the Hibernate ORM extension.

You can also run queries directly on your MongoClient object for expanded query functionality.

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 int runtime;
private String[] cast;
public Movie(String title, String plot, int year, int runtime, String[] cast) {
this.title = title;
this.plot = plot;
this.year = year;
this.runtime = runtime;
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 int getRuntime() {
return runtime;
}
public void setRuntime(int runtime) {
this.runtime = runtime;
}
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.

Note

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. The examples in this guide use a Session. To learn more about persistence contexts, see the Transactions and Sessions guide.

To run a native MongoDB query, specify a MongoDB Query Language (MQL) statement that includes the collection to query and your query criteria in an aggregation pipeline.

Tip

Aggregation Pipeline

To learn more about constructing aggregation pipelines and running aggregation operations, see the Aggregation Pipeline reference in the MongoDB Server manual.

MQL statements have the following format:

String mqlSyntax = """
{
aggregate: "<collection to query>",
pipeline: [
<aggregation pipeline stages>
]
}
""";

Important

$project Stage Requirements

The aggregation pipeline in your MQL statement must include a $project stage. To return the query documents as entity instances, you must specify each entity field other than the primary key field in the $project stage.

Then, pass the MQL statement to the createNativeQuery() method. You cannot run native queries that use parameter values. Instead, specify your search terms within the MQL statement.

You can use native queries to perform the following operations:

This example runs a native query on the sample_mflix.movies collection by passing an MQL statement to the createNativeQuery() method. The code specifies the following aggregation pipeline stages:

  • $match: Filters for documents that have a title field value of "The Parent Trap"

  • $sort: Sorts the matching documents by their year fields in descending order

  • $project: Returns each document field defined in the Movie entity

String nativeQuery = """
{
aggregate: "movies",
pipeline: [
{ $match: { title: { $eq: "The Parent Trap" } } },
{ $sort: { year: -1 } },
{ $project: { title: 1, plot: 1, year: 1, runtime: 1, cast: 1 } }
]
}
""";
var results = session.createNativeQuery(nativeQuery, Movie.class)
.getResultList();
for (Movie movie : results) {
System.out.println("Title: " + movie.getTitle() + ", Year: " + movie.getYear());
}
Title: The Parent Trap, Year: 1998
Title: The Parent Trap, Year: 1961

The Hibernate ORM extension does not currently support HQL or JPQL statements that use arithmetic operators. However, you can perform arithmetic operations on your data by using MongoDB's arithmetic operators in an MQL statement.

Tip

Arithmetic Operators

To learn more about Hibernate and MongoDB arithmetic operators, see the following resources:

The following example runs a native query on the sample_mflix.movies collection that performs the following actions:

  • Specifies a $match stage to match documents that have a year value greater than 2000 and a runtime field that exists

  • Specifies an $addFields stage to add a new field called runtimeHours

  • Uses the $divide arithmetic operator to convert the runtime value from minutes to hours for the new runtimeHours field

  • Specifies a $project stage to return each document field defined in the Movie entity, other than the primary key field

  • Prints the title value of each updated document

String nativeQuery = """
{
aggregate: "movies",
pipeline: [
{ $match: { year: { $gt: 2000 }, runtime: { $exists: true } } },
{ $addFields: {
runtimeHours: { $divide: [ "$runtime", 60 ] }
}},
{ $project: {
title: 1,
plot: 1,
year: 1,
runtime: 1,
cast: 1
}}
]
}
""";
var results = session.createNativeQuery(nativeQuery, Movie.class)
.getResultList();
for (Movie result : results) {
System.out.println("Added field to movie: " + result.getTitle());
}
Added field to movie: Kate & Leopold
Added field to movie: Crime and Punishment
Added field to movie: Glitter
Added field to movie: The Manson Family
Added field to movie: The Dancer Upstairs
Added field to movie: Fantastic Four
...

You can run native queries to perform MongoDB Search queries on your database, which are fine-grained text searches on your data. These queries provide advanced search functionality, such as matching text phrases, scoring results for relevance, and highlighting matches.

Important

You cannot run a MongoDB Search query inside a transaction.

To specify a Search query, create a Search index that covers the fields you want to query. Then, pass an aggregation pipeline to your createNativeQuery() method that includes a $search or $searchMeta stage.

Tip

MongoDB Search

To learn more about MongoDB Search queries and indexes, see MongoDB Search Overview in the MongoDB Server manual.

This example runs a Search query by passing the $search pipeline stage to the createNativeQuery() method. The code performs the following actions:

  • Specifies the Search index that covers the plot field. Ensure that you replace the <indexName> placeholder with your Search index name.

  • Queries for documents whose plot values contain the string "whirlwind romance" with no more than 3 words between them

  • Specifies a $project stage to return each document field defined in the Movie entity, other than the primary key field

  • Prints the title and plot values of the matching documents

String nativeQuery = """
{
aggregate: "movies",
pipeline: [
{
$search: {
index: "<indexName>",
phrase: {
path: "plot",
query: "whirlwind romance",
slop: 3
}
}
},
{
$project: {
title: 1,
plot: 1,
year: 1,
runtime: 1,
cast: 1
}
}
]
}
""";
var results = session.createNativeQuery(nativeQuery, Movie.class)
.getResultList();
for (Movie result : results) {
System.out.println("Title: " + result.getTitle() + ", Plot: " + result.getPlot());
}
Title: Tokyo Fiancèe, Plot: A young Japanophile Belgian woman in Tokyo falls into a whirlwind romance with a Francophile Japanese student.
Title: Designing Woman, Plot: A sportswriter and a fashion-designer marry after a whirlwind romance, and discover they have little in common.
Title: Vivacious Lady, Plot: On a quick trip to the city, young university professor Peter Morgan falls in love with nightclub performer Francey Brent and marries her after a whirlwind romance. But when he goes back ...
Title: Ek Hasina Thi, Plot: A woman falls for a charming and mysterious businessman. The whirlwind romance turns sour when she is framed for his underworld crimes. Now, finally out of prison she is ready for sweet revenge.
Title: Kick, Plot: An adrenaline junkie walks away from a whirlwind romance and embraces a new life as a thief, though he soon finds himself pursued by veteran police officer and engaged in a turf war with a local gangster.
Title: A Tale of Winter, Plot: Felicie and Charles have a serious if whirlwind holiday romance. Due to a mix-up on addresses they lose contact, and five years later at Christmas-time Felicie is living with her mother in ...

If you want to run database operations that neither the createQuery() method nor the createNativeQuery() method supports, you can operate on a MongoClient object directly in your Java application. When working with the MongoClient, you can access the MongoDB Java Sync Driver's functionality.

Tip

Feature Support

To learn more about unsupported MongoDB features that you must use a MongoClient object to access, see the Hibernate ORM Feature Compatibility page.

To learn how to use the Java driver to interact with MongoDB, see the MongoDB Java Driver documentation.

You cannot use the Hibernate ORM extension to create indexes on a collection, but you can instantiate a MongoClient and use the Java driver's createIndex() method. The following code creates a title field index on the sample_mflix.movies collection:

// Replace the <connection URI> placeholder with your MongoDB connection URI
String uri = "<connection URI>";
MongoClient mongoClient = MongoClients.create(uri);
MongoDatabase db = mongoClient.getDatabase("sample_mflix");
MongoCollection<Document> collection = db.getCollection("movies");
String indexResult = collection.createIndex(Indexes.ascending("title"));
System.out.println(String.format("Index created: %s", indexResult));
Index created: title_1

To learn more about how to use the Java driver to create indexes, see the Indexes guide in the Java driver documentation.

To learn more about the query languages discussed in this guide, see the following resources:

Back

Specify a Query

On this page