Overview
En esta guía, aprenderás a usar la Extensión MongoDB para Hibernate ORM para ejecutar operaciones de crear, leer, actualizar y borrar (CRUD) en tus colecciones MongoDB.
Datos de muestra
Los ejemplos de esta guía utilizan la entidad Movie, que representa la colección sample_mflix.movies del conjuntos de datos de muestras de Atlas. La entidad Movie tiene la siguiente definición:
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; public class Movie { private ObjectId id; private String title; private String plot; private int year; private List<String> cast; private List<String> directors; private Instant released; private Awards awards; 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; } }
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, debes ejecutar operaciones dentro de un contexto de persistencia usando un Hibernate Session o una Persistencia Jakarta EntityManager. También debes ejecutar operaciones de guardar dentro de una transacción para modificar datos de MongoDB y mantener la integridad de los datos.
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.
Insertar documentos
Crea un documento pasando una instancia de entidad a los siguientes métodos, que insertan el documento correspondiente en tu colección:
org.hibernate.Session.persist(): Utiliza la API de Hibernate para aplicar tus cambios a la base de datosjakarta.persistence.EntityManager.persist(): Usa la API de persistencia de Jakarta para aplicar tus cambios a la base de datos
Tip
Para obtener más información sobre la creación de instancias de entidades y su persistencia en la base de datos, consulta Haciendo persistentes las entidades en la guía para usuarios de Hibernate ORM.
Ejemplo
El siguiente ejemplo crea una nueva instancia de entidad Movie y utiliza el método persist() para insertar un documento correspondiente en la colección sample_mflix.movies:
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);
Lea los documentos
Para recuperar documentos de tu colección, proporciona los criterios de tu query al método createQuery(). Las siguientes APIs proporcionan el método createQuery():
API
Sessionde Hibernate: Usa la sintaxis de Hibernate Query Language (HQL) para definir tus consultasAPI
EntityManagerde Jakarta Persistence: Usa la sintaxis de Jakarta Persistence Query Language (JPQL), que es un subconjunto de HQL, para definir tus consultas.
Tip
Para obtener más información sobre cómo aprender a recuperar datos utilizando la sintaxis HQL y JPQL, consulta Instrucciones select en la guía de query Hibernate ORM.
Nota
Esta sección describe cómo leer documentos utilizando HQL y JPQL, pero también se puede utilizar el generador de criterios o consultas nativas para recuperar datos. Para obtener más información, consulta las siguientes guías:
Ejemplo de devolución de un documento
Para recuperar solo un documento que coincida con tus criterios de query, encadena el método getSingleResult() al método createQuery(). El siguiente ejemplo recupera un documento que tiene un valor de title de "Boyhood" de la colección sample_mflix.movies:
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 sintaxis
Para obtener más información sobre la sintaxis de HQL y JPQL, consulta Una guía sobre Hibernate languaje del query en la documentación de Hibernate ORM.
Ejemplo de retorno de varios documentos
El siguiente ejemplo llama al método createQuery() en una sesión para recuperar documentos de la colección sample_mflix.movies. El código utiliza HQL y JPQL para devolver documentos que tienen un valor de year igual a 1920 e imprime sus valores de title:
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()));
Modificar documentos
Puedes realizar las siguientes operaciones para modificar documentos en una colección:
Actualizar un documento: Llama a los métodos setter de tu entidad para cambiar los valores de los campos de una instancia de entidad y luego utiliza una sesión o un administrador de entidades para guardar tus cambios.
Actualizar documentos múltiples: Pasa una instrucción de actualizar a los métodos
createQuery()ocreateMutationQuery()en una sesión o administrador de entidades. Luego, llama al métodoexecuteUpdate()para aplicar tus cambios a la base de datos.
Tip
Para obtener más información sobre cómo modificar datos utilizando Hibernate ORM, consulta los siguientes recursos:
Modificando el estado gestionado/persistente en la guía del usuario de Hibernate ORM
Actualizar instrucciones en la guía de query de Hibernate ORM
Actualizar un ejemplo
El siguiente ejemplo recupera un documento por su valor ObjectId. Luego, el ejemplo llama al método setTitle() de la entidad Movie para actualizar el valor title del documento a "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);
Actualizar múltiples ejemplo
El siguiente ejemplo actualiza el valor de title de los documentos coincidentes de "The Three Stooges" a "The 3 Stooges". Luego, el ejemplo llama al método executeUpdate() para aplicar los cambios a la base de datos:
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);
La cláusula SET de una instrucción de actualización masiva también puede usar una expresión en lugar de un valor literal. La expresión puede hacer referencia al campo que se está actualizando o a otro campo de la entidad.
El siguiente ejemplo utiliza una expresión aritmética para incrementar el valor year de los documentos que tienen un valor title igual a "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);
El siguiente ejemplo utiliza una referencia de campo para establecer el valor plot para que coincida con el valor title para los documentos que tienen un valor year de 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);
Ejemplo de actualización múltiple basada en lógica condicional
El siguiente ejemplo utiliza una expresión CASE para establecer el valor plot dependiendo de si el valor year de cada documento es posterior al año 2000. La extensión Hibernate ORM traduce la expresión CASE al operador $switch de MongoDB y aplica la actualización mediante una etapa de canalización $set:
var updateResult = session.createMutationQuery( "update Movie m set m.plot = case when m.year > 2000 then 'Modern release' " + "else 'Classic release' end where m.title = :title") .setParameter("title", "The 3 Stooges") .executeUpdate(); System.out.println("Number of movies updated: " + updateResult);
Para obtener más información sobre las expresiones CASE, consulte la sección Expresiones de casos de uso para lógica condicional en la guía Especificar una consulta.
Realizar inserción de documentos
Una operación de inserción o actualización (upsert) actualiza un documento si existe uno coincidente, o inserta uno nuevo si no existe ninguno. Para realizar una operación upsert, utilice el método upsert() o upsertMultiple(). Estos métodos solo están disponibles en la API StatelessSession de Hibernate.
Nota
Una instancia StatelessSession no registra los cambios en las entidades que recupera. Para guardar los cambios en una entidad, pásela a otro método de escritura. Utilice StatelessSession para flujos de trabajo de escritura masiva.
Requisitos de la entidad
La extensión Hibernate ORM crea el filtro para una operación upsert a partir del identificador de su entidad, por lo que su aplicación debe asignar el valor del identificador antes de llamar a upsert().
El método upsert() no genera valores de identificador, incluso si su entidad utiliza la anotación @ObjectIdGenerator. Si no asigna un valor de identificador, la extensión Hibernate ORM almacena el documento con un valor null _id.
Puedes usar la anotación @Column(updatable = false) para proteger un campo de las actualizaciones durante una operación de inserción/actualización. La siguiente definición de entidad Movie anota el campo released con @Column(updatable = false), lo que indica a la extensión ORM de Hibernate que escriba en el campo cuando inserte un documento, pero que lo omita cuando actualice un documento existente:
public class Movie { private ObjectId id; private String title; private int year; private Instant released; // Getters and setters omitted }
La extensión Hibernate ORM envía los campos que son tanto insertables como actualizables en el operador $set de la instrucción de actualización generada. Envía los campos que solo son insertables, como los campos anotados con @Column(updatable = false), en el operador $setOnInsert.
Insertar un ejemplo
El siguiente ejemplo crea una instancia de entidad Movie y la pasa al método upsert(). Si existe un documento con el valor ObjectId especificado, la extensión Hibernate ORM actualiza los valores title y year de dicho documento. De lo contrario, la extensión Hibernate ORM inserta un nuevo documento.
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); }
Ejemplo múltiple de inserción/actualización
Para insertar o actualizar varias instancias de entidad en una sola operación, pase una lista de instancias al método upsertMultiple(). El siguiente ejemplo inserta o actualiza dos instancias de entidad Movie:
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)); }
Limitaciones de Upsert
Las siguientes asignaciones de entidades no son compatibles con las operaciones de inserción/actualización. Cuando se inserta/actualiza una entidad que utiliza una de estas asignaciones, la extensión Hibernate ORM genera un error FeatureNotSupportedException:
Entidades que tienen un campo anotado con
@Version.Entidades que tienen un campo anotado con
@Column(insertable = false). El lenguaje de consulta de MongoDB no proporciona ninguna forma de escribir un campo solo cuando una operación coincide con un documento existente.Entidades cuyo único atributo persistente es el identificador. Una operación de actualización o inserción en este tipo de entidad no tiene campos que actualizar, por lo que la extensión Hibernate ORM rechaza la operación.
Delete Documents
Puedes realizar las siguientes operaciones para borrar documentos de una colección:
Borrar un documento: Llama al método
remove()en una sesión o administrador de entidades, pasando la instancia de entidad que deseas borrar como argumento.Eliminar varios documentos: Proporcione una instrucción de borrado a los métodos
createQuery()ocreateMutationQuery()en una sesión o administrador de entidades. A continuación, llama al métodoexecuteUpdate()para aplicar los cambios a la base de datos.
Tip
Para obtener más información sobre el borrado de datos con Hibernate ORM, consulta los siguientes recursos:
Borrando entidades en la guía del usuario de Hibernate ORM
Borrar instrucciones en la guía de query de Hibernate ORM
Borrar un ejemplo
El siguiente ejemplo recupera un documento por su valor de ObjectId. Luego, el ejemplo llama al método remove() en una sesión para borrar el documento correspondiente de la colección sample_mflix.movies:
// 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);
Borrar Múltiples ejemplos
El siguiente ejemplo elimina todos los documentos que tienen un valor year de 1920 de la colección sample_mflix.movies. El ejemplo pasa una instrucción de borrado al método createMutationQuery() y luego llama al método executeUpdate() para aplicar los cambios a la base de datos:
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);
Información Adicional
Para obtener más información sobre cómo realizar operaciones CRUD utilizando Hibernate ORM, consulta los siguientes recursos:
Contexto de persistencia en la guía del usuario de Hibernate ORM
Tipos de instrucciones en la guía de query de Hibernate ORM
Para ver más ejemplos de creación, lectura, actualización y borrar, consulta las siguientes secciones del tutorial Comenzar:
Para obtener más información sobre cómo utilizar la extensión Hibernate ORM para ejecutar consultas, consulta las siguientes guías: