Overview
在本指南中,您可以学习如何使用MongoDB Extension for Hibernate ORM 来执行事务。事务允许您运行一系列仅在提交整个ACID 事务后才更改数据的操作。
在MongoDB中,事务在逻辑会话中运行。会话是要按顺序运行的一组相关读取或写入操作。会话启用为一群组操作启用因果一致性,并允许您在符合ACID的ACID 事务中运行操作,该ACID 事务满足原子性、一致性、隔离性和持久性的预期。
Hibernate ORM 扩展支持以下用于管理会话和事务的 API:
Hibernate
Session:允许您使用org.hibernate.TransactionAPI 对数据库操作进行分组。要学习;了解详情,请参阅 Hibernate ORM 用户指南中的 Hibernate Transaction API。Jakarta Persistence
EntityManager:指示 Hibernate ORM 在内部托管Session,并允许您使用jakarta.persistence.EntityTransactionAPI 对数据库操作进行分组。要学习;了解更多信息,请参阅 Jakarta EE 文档中的jakarta.persistence包。
样本数据
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 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; } }
要学习如何创建Java应用程序以使用MongoDB Extension for Hibernate ORM与此MongoDB示例集合交互,请参阅 入门教程。
创建会话
要与MongoDB数据交互,您必须在会话中运行所有数据库操作。本节介绍如何通过以下方式管理数据库会话:
使用 Hibernate 会话:使用 Hibernate 的原生API从
SessionFactory创建Session使用 JPA EntityManager:使用 Jakarta Persistence API 从
EntityManagerFactory创建EntityManager
使用 Hibernate 会话
提示
在使用 Session 之前,您必须创建一个配置 SessionFactory 的 HibernateUtil.java文件。要学习;了解更多信息,请参阅入门教程中的配置应用程序步骤。
要启动 Hibernate Session,请执行以下步骤:
使用
getSessionFactory()方法从HibernateUtil实用程序类中检索SessionFactory。SessionFactory存储您的MongoDB连接配置,并且可以打开新的数据库会话。通过在
SessionFactory实例上调用openSession()方法来创建Session。运行数据库操作后,对这两个实例使用
close()方法关闭SessionFactory和Session。
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
还可以使用 Java 的 try-with-resources 声明 来简化会话管理逻辑并自动关闭会话,如以下代码所示:
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();
使用 JPA EntityManager
提示
在使用 EntityManager 之前,您必须创建一个声明持久性单元的 persistence.xml文件。要学习;了解更多信息,请参阅 Hibernate ORM 文档中的使用 JPA 标准 API 的教程。
要启动 Jakarta Persistence API (JPA) EntityManager,请执行以下步骤:
通过调用
createEntityManagerFactory()方法从persistence.xml文件创建EntityManagerFactory,该方法会在内部创建SessionFactory。通过对
EntityManagerFactory实例调用createEntityManager()方法来创建EntityManager,这会在内部创建Session。运行数据库操作后,在
EntityManagerFactory和EntityManager实例上调用close()方法以关闭这两个实例。
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
在 Jakarta Persistence v3.1 或更高版本中,您可以使用 Java 的 try-with-resources 声明 自动关闭 EntityManager,如 Hibernate 会话 部分所示。
运行事务
要修改MongoDB数据,必须在ACID 事务中运行所有写入操作。本节介绍如何通过以下方式托管ACID 事务:
使用 Hibernate 事务:使用 Hibernate 的原生
org.hibernate.TransactionAPI 从Session启动事务使用 JPA ACID 事务:使用
jakarta.persistence.EntityTransactionAPI 从EntityManager
使用 Hibernate 事务
要启动 Hibernate Transaction,请在 Session实例上调用 beginTransaction() 方法。运行操作并使用 persist() 方法在会话中注册更改后,通过调用 commit() 方法提交ACID 事务。
以下示例使用ACID 事务对 sample_mflix.movies集合执行以下操作:
创建新的
Movie实体并将其作为文档插入到集合更新
title值为"Black Swan"的文档的cast字段
突出显示的行开始并提交ACID 事务:
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();
使用 JPA EntityTransaction
要创建 JPA EntityTransaction,请对 EntityManager 调用 getTransaction() 方法。此方法检索一个 EntityTransaction,其中包装了根本的Hibernate Transaction。然后,调用 begin() 方法启动ACID 事务。运行操作并使用 persist() 方法向实体管理器注册更改后,通过调用 commit() 方法提交事务。
以下示例使用 EntityTransaction 从 sample_mflix.movies集合中删除一个文档,然后插入一个标题值为 "The Favourite" 的新文档。突出显示的行开始并提交ACID 事务:
// 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();
事务错误处理
要放弃ACID 事务中的所有数据更改,请对 Hibernate Transaction 或 JPA EntityTransaction 调用 rollback() 方法。调用此方法后,Hibernate ORM 将恢复未提交的更改并清除持久化上下文。
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(); }
更多信息
要学习;了解有关会话和实体经理人的更多信息,请参阅 Hibernate ORM 文档中的持久化上下文。
要学习;了解有关事务的更多信息,请参阅 事务 Hibernate ORM 文档中的事务。