Overview
En esta guía, puedes aprender a utilizar la extensión MongoDB para Hibernate ORM para realizar transacciones. Las transacciones te permiten ejecutar una serie de operaciones que modifican datos solo si la transacción completa se confirma.
En MongoDB, las transacciones se ejecutan dentro de sesiones lógicas. Una sesión es un grupo de operaciones de lectura o escritura relacionadas que deseas ejecutar de manera secuencial. Las sesiones permiten una coherencia causal para un grupo de operaciones y permiten ejecutar operaciones en una transacción compatible con ACID , que es una transacción que cumple con la expectativa de atomicidad, coherencia, aislamiento y durabilidad.
La extensión de Hibernate ORM admite las siguientes APIs para gestionar sesiones y transacciones:
Hibernar
SessionPermite utilizar la APIorg.hibernate.Transactionpara agrupar las operaciones de la base de datos. Para obtener más información, consulte API de Transacción Hibernate en la guía del usuario de Hibernate ORM.Jakarta Persistence
EntityManager: indica al Hibérnate ORM que gestione unSessioninternamente y le permite utilizar la APIjakarta.persistence.EntityTransactionpara agrupar las operaciones de su base de datos. Para obtener más información, consulta el paquete jakarta.persistence en la documentación de Jakarta EE.
Datos de muestra
Los ejemplos de esta guía utilizan la Movie entidad, que representa la sample_mflix.movies colección de los conjuntos de datos de muestra del Atlas. La Movie entidad 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 use la extensión MongoDB para Hibernate ORM para interactuar con esta colección de muestra de MongoDB, consulte Comenzar tutorial.
Crear una sesión
Para interactuar con los datos de MongoDB, debe ejecutar todas las operaciones de base de datos en una sesión. Esta sección muestra cómo administrar una sesión de base de datos de las siguientes maneras:
Utilice una sesión de Hibernate: utilice la API nativa de Hibernate para crear un a partir de
SessionunSessionFactoryUtiliza un EntityManager de JPA: Utiliza la API de persistencia de Jakarta para crear un
EntityManagerdesde unEntityManagerFactory
Utilice una sesión de hibernación
Tip
Antes de usar un Session, debes crear un archivo HibernateUtil.java que configure un SessionFactory. Para aprender más, consulta el paso Configura tu aplicación del tutorial de Introducción.
Para iniciar una Hibernate Session, realiza los siguientes pasos:
Recupere un
SessionFactoryde su clase utilitariaHibernateUtilutilizando el métodogetSessionFactory(). ElSessionFactoryalmacena tu configuración de conexión MongoDB y puede abrir nuevas sesiones de base de datos.Cree un
Sessionllamando al métodoopenSession()en su instanciaSessionFactory.Después de ejecutar operaciones en la base de datos, cierra tu
SessionFactoryySessionutilizando el métodoclose()en ambas instancias.
El siguiente ejemplo ejecuta una consulta de base de datos en una sesión y recupera un documento que tiene un valor title de "Erin Brockovich" de la colección sample_mflix.movies:
var sf = HibernateUtil.getSessionFactory(); Session session = sf.openSession(); var movie = session.createQuery("from Movie where title = :t", Movie.class) .setParameter("t", "Erin Brockovich") .getSingleResult(); System.out.println("Title: " + movie.getTitle() + ", Year: " + movie.getYear()); session.close(); sf.close();
Title: Erin Brockovich, Year: 2000
También puedes utilizar la instrucción try-with-resources de Java para simplificar la lógica de gestión de sesiones y cerrar automáticamente la sesión, como se muestra en el siguiente código:
var sf = HibernateUtil.getSessionFactory(); try (Session session = sf.openSession()) { var movie = session.createQuery("from Movie where title = :t", Movie.class) .setParameter("t", "Erin Brockovich") .getSingleResult(); System.out.println("Title: " + movie.getTitle() + ", Year: " + movie.getYear()); } sf.close();
Utilice un EntityManager de JPA
Tip
Antes de 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.
Para iniciar una EntityManager de la API de persistencia de Jakarta (JPA), realiza los siguientes pasos:
Cree un
EntityManagerFactorya partir de su archivopersistence.xmlllamando al métodocreateEntityManagerFactory(), que crea unSessionFactoryinternamente.Cree un
EntityManagerllamando al métodocreateEntityManager()en su instancia deEntityManagerFactory, que crea unSessioninternamente.Después de ejecutar las operaciones de base de datos, cierre
EntityManagerFactoryyEntityManagerllamando al métodoclose()en ambas instancias.
El siguiente ejemplo ejecuta una consulta de base de datos en un administrador de entidades y recupera documentos que tienen un valor year de 1929 de la colección sample_mflix.movies:
// Replace <persistence unit> with the name of your persistence unit in the persistence.xml file EntityManagerFactory emf = Persistence.createEntityManagerFactory("<persistence unit>"); EntityManager entityManager = emf.createEntityManager(); var results = entityManager.createQuery("select m from Movie m where m.year = :y", Movie.class) .setParameter("y", 1929) .getResultList(); results.forEach(movie -> System.out.println(movie.getTitle())); entityManager.close(); emf.close();
The Broadway Melody Queen Kelly Asphalt Hallelujah Disraeli Applause Lambchops
En Jakarta Persistence v3.1 o posterior, puedes usar la instrucción try-with-resources de Java para cerrar automáticamente el EntityManager, como se muestra en la sección Hibernate Session.
Ejecutar una Transacción
Para modificar los datos de MongoDB, debe ejecutar todas las operaciones de escritura en una transacción. Esta sección muestra cómo gestionar una transacción de las siguientes maneras:
Utilizar una Transacción de Hibernate: Utiliza la API nativa de
org.hibernate.Transactionde Hibernate para iniciar una transacción desde unSession.Utiliza una EntityTransaction JPA: Usa la API de
jakarta.persistence.EntityTransactionpara iniciar una transacción desde unEntityManager
Utilice una transacción de Hibernate
Para iniciar un Hibernate Transaction, llama al método beginTransaction() en una instancia de Session. Después de ejecutar las operaciones y utilizar el método persist() para registrar tus cambios con la sesión, confirma la transacción llamando al método commit().
El siguiente ejemplo usa una transacción para realizar las siguientes operaciones en la colección sample_mflix.movies:
Crea una nueva entidad
Moviey la inserta como un documento en la colecciónActualiza el campo
castde un documento que tiene un valortitlede"Black Swan"
Las líneas resaltadas inician y confirman la transacción:
var sf = HibernateUtil.getSessionFactory(); Session session = sf.openSession(); Transaction tx = session.beginTransaction(); var newMovie = new Movie(); newMovie.setTitle("Lady Bird"); newMovie.setYear(2017); session.persist(newMovie); var movie = session.createQuery("from Movie where title = :t", Movie.class) .setParameter("t", "Black Swan") .getSingleResult(); var currentCast = new ArrayList<>(movie.getCast()); currentCast.add("Winona Ryder"); movie.setCast(currentCast); tx.commit(); session.close(); sf.close();
Utilice una entidad JPA Transaction
Para crear un/una JPA EntityTransaction, llama al método getTransaction() en tu EntityManager. Este método recupera un EntityTransaction, que envuelve el subyacente Hibernate Transaction. A continuación, llama al método begin() para iniciar la transacción. Después de ejecutar operaciones y de utilizar el método persist() para registrar los cambios con el administrador de entidades, confirmar la transacción llamando al método commit().
El siguiente ejemplo utiliza un EntityTransaction para borrar un documento de la colección sample_mflix.movies y luego insertar un nuevo documento que tenga un valor de título de "The Favourite". Las líneas resaltadas inician y confirman la transacción:
// Replace <persistence unit> with the name of your persistence unit in the persistence.xml file EntityManagerFactory emf = Persistence.createEntityManagerFactory("<persistence unit>"); EntityManager entityManager = emf.createEntityManager(); entityManager.getTransaction().begin(); // Your ObjectId value might differ Movie movieToDelete = entityManager.find(Movie.class, new ObjectId("573a1399f29313caabcedc5d")); entityManager.remove(movieToDelete); var addMovie = new Movie(); addMovie.setTitle("The Favourite"); addMovie.setYear(2018); entityManager.persist(addMovie); entityManager.getTransaction().commit(); entityManager.close(); emf.close();
Gestión de errores de transacción
Para descartar todos los cambios de datos de una transacción, llama al método rollback() en un Hibernate Transaction o en un JPA EntityTransaction. Después de llamar a este método, el Hibernate ORM revierte los cambios no confirmados y limpia el contexto de persistencia.
El siguiente ejemplo revierte la transacción si el código genera un error. Elija el Hibernate Transaction o la pestaña JPA EntityTransaction para ver el código correspondiente:
Session session = sessionFactory.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); Movie movie = new Movie(); movie.setTitle("Control Alt Delete"); session.persist(movie); tx.commit(); } catch (Exception e) { if (tx != null) { tx.rollback(); } e.printStackTrace(); } finally { session.close(); }
EntityManager entityManager = emf.createEntityManager(); EntityTransaction tx = entityManager.getTransaction(); try { tx.begin(); Movie movie = new Movie(); movie.setTitle("Control Alt Delete"); entityManager.persist(movie); tx.commit(); } catch (Exception e) { if (tx != null && tx.isActive()) { tx.rollback(); } e.printStackTrace(); } finally { entityManager.close(); }
Información Adicional
Para obtener más información sobre sesiones y administradores de entidades, consulta Contexto de Persistencia en la documentación de Hibernate ORM.
Para obtener más información sobre transacciones, consulta Transacciones en la documentación de Hibernate ORM.