Overview
En esta guía, puedes aprender a utilizar la extensión de MongoDB para Hibernate ORM para especificar una query de base de datos.
Se puede refinar el conjunto de documentos que una query retorna creando un filtro de query. Un filtro de query es una expresión que especifica los criterios de búsqueda que MongoDB usa para emparejar documentos en una operación de lectura o guardado. Para crear filtros de query de MongoDB, utiliza Hibernate Query Language (HQL) o instrucciones Jakarta Persistence Query Language (JPQL).
Tip
Para aprender más acerca de la sintaxis de HQL y JPQL, consulta Una guía para el lenguaje de consulta Hibernate en la documentación de Hibernate ORM.
Nota
Soporte de query
La extensión MongoDB para Hibernate ORM no es compatible con todas las funciones de consulta de MongoDB e Hibernate. Para obtener más información, consulte Soporte de query en la página de compatibilidad de funcionalidades.
Datos de muestra
Los ejemplos de esta guía utilizan el Movie entidad, que representa la colección sample_mflix.movies de los conjuntos de datos de muestra de Atlas. La entidad Movie tiene la siguiente definición:
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; public class Movie { private ObjectId id; private String title; private String plot; private int year; private List<String> cast; public Movie(String title, String plot, int year, List<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 List<String> getCast() { return cast; } public void setCast(List<String> cast) { this.cast = cast; } }
Para aprender a crear una aplicación Java que utilice la extensión MongoDB para Hibernate ORM para interactuar con esta colección de muestra de MongoDB, consulta el tutorial Primeros pasos.
Importante
Contextos de Persistencia
Para habilitar que Hibernate ORM interactúe con la base de datos, debe ejecutar operaciones dentro de un contexto de persistencia utilizando un Session de Hibernate o un EntityManager de Jakarta Persistence. Use HQL para definir consultas de sesión y use JPQL para definir consultas de administrador de entidades.
Antes de ejecutar los ejemplos en esta guía, asegúrate de añadir código de contexto de persistencia y gestión de transacciones a tu aplicación que se asemeje al siguiente código:
var sf = HibernateUtil.getSessionFactory(); Session session = sf.openSession(); Transaction tx = session.beginTransaction(); // ... Perform CRUD operations here tx.commit(); session.close(); sf.close();
Para utilizar una sesión, debes crear un archivo HibernateUtil.java que configure un SessionFactory. Para obtener más información, consulta el paso Configura tu aplicación del tutorial Comenzar.
// 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;
Para usar un EntityManager, debes crear un archivo persistence.xml que declare una unidad de persistencia. Para aprender más, consulta el Tutorial utilizando APIs estándar JPA en la documentación de Hibernate ORM.
Ejecutar una consulta
Para query tus datos de MongoDB, llama al método createQuery() sobre una sesión o un entity manager. Luego, especifica tus criterios de coincidencia en una instrucción de Hibernate languaje del query (HQL) o Jakarta Persistence languaje del query (JPQL).
En esta sección se describe cómo realizar las siguientes operaciones de consulta:
Recuperar todos los documentos
Para recuperar todos los documentos de una colección, pasa una instrucción select básica al método createQuery(). En esta instrucción, especifica la entidad que representa la colección que deseas consultar.
El siguiente ejemplo recupera los valores de title de todos los documentos de la colección sample_mflix.movies consultando la entidad Movie:
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? ...
Recuperar documentos coincidentes
Para recuperar documentos que cumplan criterios específicos, pase una sentencia SELECT con una cláusula where al método createQuery(). En esta sentencia, especifique la entidad que representa la colección que desea consultar y los criterios de coincidencia.
El siguiente ejemplo recupera documentos que tienen un valor title de "Romeo and Juliet" de la colección sample_mflix.movies:
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
Para recuperar un solo documento que coincida con criterios específicos, encadena el método getSingleResult() al método createQuery().
El siguiente ejemplo recupera un único documento que tiene un valor title de "Best in Show" de la colección sample_mflix.movies:
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
Importante
Errores NonUniqueResultException
Si tu query coincide con varios documentos, el método getSingleResult() genera un error NonUniqueResultException. Para evitar este error, asegúrate de que tu query coincida con un solo documento o limita los resultados de tu query a un solo documento.
Ejecutar queries de la API de criterios
En lugar de usar instrucciones HQL o JPQL para crear filtros de query, puedes utilizar la API de Criterios de Jakarta Persistence para compilar queries tipadas de manera programática.
Para crear una consulta utilizando la API de criterios, realice las siguientes acciones:
Cree un objeto
CriteriaBuildera partir de una sesión o un gestor de entidades.Crear un objeto
CriteriaQuerydesde el generador y especificar la entidad a query.Utilice los métodos de consulta proporcionados por la clase
CriteriaQuerypara especificar sus criterios de consulta.
Tip
Para obtener más información sobre la API de criterios, consulte Uso de la API de criterios para crear consultas en la documentación de Jakarta EE.
El siguiente ejemplo utiliza la API de Criteria para recuperar todos los documentos que tienen un valor de year igual a 1925 de la colección sample_mflix.movies:
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
Ejecuta consultas nativas
Para ejecutar queries de MongoDB actualmente no admitidas por la extensión de Hibernate ORM, puedes pasar tu query como una instrucción MongoDB Query Language (MQL) al método createNativeQuery().
Para aprender a ejecutar consultas nativas, consulte la guía Realizar Consultas Nativas.
Personaliza tu filtro de consulta
En esta sección se describe cómo utilizar operadores para crear los siguientes tipos de filtros de consulta:
Tip
Usar Filtros Comparativos
Nota
La extensión Hibernate ORM no admite todos los operadores de comparación, incluyendo LIKE y BETWEEN. Para obtener más información sobre las limitaciones de soporte, consulta Soporte de query en la página de Compatibilidad de funciones.
Puedes utilizar los siguientes operadores en tus instrucciones de query para comparar los valores de los campos con valores de query especificados:
=: Coincidencia de igualdad<>Coincidencia de desigualdades>: Comparaciones mayores que>=: Comparaciones mayores o iguales<: Comparaciones menores que<=: Comparaciones menores o iguales
El siguiente ejemplo recupera documentos que tienen un valor de year mayor o igual a 2015 de la colección sample_mflix.movies:
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 ...
Utilizar filtros lógicos
Puede usar los siguientes operadores en sus sentencias de consulta para combinar múltiples criterios de consulta:
and: Coincidencia con todos los criteriosorCoincide con cualquier criterionot: Invert criteria
El siguiente ejemplo recupera un documento que tiene un valor de title de "The Godfather" y un valor de year de 1972 de la colección sample_mflix.movies:
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
Modificar resultados de queries
Esta sección describe cómo modificar los resultados de la query de las siguientes maneras:
Ordenar resultados
Puede ordenar los resultados de la query por el valor de un campo especificado utilizando la cláusula order by en su instrucción de query. Por defecto, la cláusula order by ordena los documentos en orden ascendente. Para ordenar los documentos en orden descendente, adjunta la palabra clave desc al nombre del campo.
El siguiente ejemplo recupera documentos coincidentes de la colección sample_mflix.movies y los ordena por el campo year en orden descendente:
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
Omitir resultados
Puede omitir un número específico de documentos en los resultados de su consulta encadenando el método setFirstResult() a la consulta. Pase el número de documentos iniciales que se omitirán como argumento a este método.
El siguiente ejemplo ejecuta la misma query que el ejemplo anterior pero omite el primer documento coincidente en los resultados:
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
Limitar los resultados
Puedes limitar el número de documentos que tu query devuelve encadenando el método setMaxResults() a la query. Pase el número máximo de documentos a devolver como argumento a este método.
El siguiente ejemplo ejecuta la misma query que el ejemplo de ordenamiento, pero devuelve hasta dos documentos coincidentes en los resultados:
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
Alternativamente, puede utilizar una cláusula limit en su instrucción HQL o JPQL para restringir el número de documentos que devuelve su query, como se muestra en el siguiente código:
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();
Consultas avanzadas de campos
Esta sección describe cómo ejecutar consultas en los siguientes campos:
Consultar un campo de clave principal
Para recuperar un documento en función de su valor ObjectId, puedes pasar ese valor como argumento al método get(), si estás usando una sesión, o al método find(), si usas un gestor de entidades.
El siguiente ejemplo recupera un documento de la colección sample_mflix.movies por su valor ObjectId:
var movieById = session.get(Movie.class, new ObjectId("573a13a8f29313caabd1d53c"));
var movieById = entityManager.find(Movie.class, new ObjectId("573a13a8f29313caabd1d53c"));
Query un campo incrustado
Puede representar documentos incrustados de MongoDB creando @Struct incrustables agregados. No puede crear filtros de consulta para valores incrustables individuales, pero puede usar la extensión ORM de Hibernate para obtener @Struct incrustables agregados asociados a entidades principales específicas.
Tip
Para obtener más información sobre cómo representar documentos incrustados, consulta Datos integrados en la guía Crear entidades.
Importante
Limitaciones de las consultas
Para aprender más información sobre las limitaciones de query para los embebidos, consulta soporte de query Hibernate en la página de Compatibilidad de funcionalidad.
El siguiente ejemplo recupera documentos con un valor title de "Hairspray" de la colección sample_mflix.movies. A continuación, el código recupera el campo awards, que almacena el incrustable agregado Awards @Struct, e imprime el campo wins del tipo incrustable Awards:
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
Consultar un campo de matriz
La extensión Hibernate ORM admite las siguientes funciones para consultar campos de arreglo:
array_contains(): Coincide documentos donde un campo de arreglo contiene un valor especificadoarray_contains_nullable(): Coincidir con documentos donde un campo de arreglo contiene un valor especificado, incluyendo valoresnullarray_includes(): Coincide con documentos donde un campo de arreglo incluye otro valor de arregloarray_includes_nullable()Coincidir con documentos donde un campo de arreglo incluya otro valor de arreglo, incluidos valoresnull
Tip
Para aprender más sobre las funciones de arrays, consulte Funciones para el manejo de arrays en la guía de usuario de Hibernate ORM.
El siguiente ejemplo utiliza la función array_contains() para recuperar documentos que tienen el valor "Kathryn Hahn" en el campo de arreglo cast de la colección sample_mflix.movies:
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
Información Adicional
Para obtener más información sobre cómo realizar otras operaciones en tus datos de MongoDB, consulta la guía Realizar Operaciones CRUD.
Para obtener más información sobre el uso de HQL y JPQL para ejecutar consultas, consulte Una guía para el lenguaje de consulta de Hibernate en la documentación de Hibernate ORM.