Overview
In this guide, you can learn how to use the MongoDB Extension for Hibernate ORM to perform transactions. Transactions allow you to run a series of operations that change data only if the entire transaction is committed.
In MongoDB, transactions run within logical sessions. A session is a grouping of related read or write operations that you want to run sequentially. Sessions enable causal consistency for a group of operations and allow you to run operations in an ACID-compliant transaction, which is a transaction that meets an expectation of atomicity, consistency, isolation, and durability.
The Hibernate ORM extension supports the following APIs for managing sessions and transactions:
Hibernate
Session: Allows you to use theorg.hibernate.TransactionAPI to group your database operations. To learn more, see Hibernate Transaction API in the Hibernate ORM user guide.Jakarta Persistence
EntityManager: Instructs the Hibernate ORM to manage aSessioninternally and allows you to use thejakarta.persistence.EntityTransactionAPI to group your database operations. To learn more, see the jakarta.persistence package in the Jakarta EE documentation.
Sample Data
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; public class Movie { 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.
Create a Session
To interact with MongoDB data, you must run all database operations in a session. This section shows how to manage a database session in the following ways:
Use a Hibernate Session: Use Hibernate's native API to create a
Sessionfrom aSessionFactoryUse a JPA EntityManager: Use the Jakarta Persistence API to create an
EntityManagerfrom anEntityManagerFactory
Use a Hibernate Session
Tip
Before using 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.
To start a Hibernate Session, perform the following steps:
Retrieve a
SessionFactoryfrom yourHibernateUtilutility class by using thegetSessionFactory()method. TheSessionFactorystores your MongoDB connection configuration and can open new database sessions.Create a
Sessionby calling theopenSession()method on yourSessionFactoryinstance.After running database operations, close your
SessionFactoryandSessionby using theclose()method on both instances.
The following example runs a database query in a session and retrieves a document
that has a title value of "Erin Brockovich" from the sample_mflix.movies
collection:
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
You can also use Java's try-with-resources statement to simplify the session management logic and automatically close the session, as shown in the following code:
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();
Use a JPA EntityManager
Tip
Before using 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 start a Jakarta Persistence API (JPA) EntityManager, perform the
following steps:
Create an
EntityManagerFactoryfrom yourpersistence.xmlfile by calling thecreateEntityManagerFactory()method, which creates aSessionFactoryinternally.Create an
EntityManagerby calling thecreateEntityManager()method on yourEntityManagerFactoryinstance, which creates aSessioninternally.After running database operations, close your
EntityManagerFactoryandEntityManagerby calling theclose()method on both instances.
The following example runs a database query in an entity manager and retrieves documents
that have a year value of 1929 from the sample_mflix.movies
collection:
// 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
In Jakarta Persistence v3.1 or later, you can use Java's
try-with-resources statement
to automatically close the EntityManager, as shown in the Hibernate Session section.
Run a Transaction
To modify MongoDB data, you must run all write operations in a transaction. This section shows how to manage a transaction in the following ways:
Use a Hibernate Transaction: Use Hibernate's native
org.hibernate.TransactionAPI to start a transaction from aSessionUse a JPA EntityTransaction: Use the
jakarta.persistence.EntityTransactionAPI to start a transaction from anEntityManager
Use a Hibernate Transaction
To start a Hibernate Transaction, call the beginTransaction() method
on a Session instance. After you run operations and use the persist() method to
register your changes with the session, commit the transaction by calling the
commit() method.
The following example uses a transaction to create a new Movie entity
and insert it as a document into the sample_mflix.movies collection.
The highlighted lines begin and commit the transaction.
var sf = HibernateUtil.getSessionFactory(); Session session = sf.openSession(); Transaction tx = session.beginTransaction(); var newMovie = new Movie(); newMovie.setTitle("Lady Bird"); session.persist(newMovie); tx.commit(); session.close(); sf.close();
Use a JPA EntityTransaction
To create a JPA EntityTransaction, call the getTransaction() method
on your EntityManager. This method retrieves a EntityTransaction,
which wraps the underlying Hibernate Transaction. Then, call the begin()
method to start the transaction. After you run operations and use the persist() method to
register your changes with the entity manager, commit the transaction by calling
the commit() method.
The following example uses an EntityTransaction to delete
a document from the sample_mflix.movies collection. The highlighted
lines begin and commit the transaction.
// 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); entityManager.getTransaction().commit(); entityManager.close(); emf.close();
Transaction Error Handling
To discard all data changes from a transaction, call the rollback()
method on a Hibernate Transaction or a JPA EntityTransaction.
After calling this method, the Hibernate ORM reverts the uncommitted changes
and clears the persistence context.
The following example rolls back the transaction if the code throws an error. Select the Hibernate Transaction or JPA EntityTransaction tab to see the corresponding code:
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(); }
Additional Information
To learn more about sessions and entity managers, see Persistence Context in the Hibernate ORM documentation.
To learn more about transactions, see Transactions in the Hibernate ORM documentation.