MongoDB.local SF, Jan 15: See the speaker lineup & ship your AI vision faster. Use WEB50 to save 50%
Find out more >
Docs 菜单
Docs 主页
/ /

指定查询

在本指南中,您可以学习如何使用 MongoDB Extension for Hibernate ORM 来指定数据库查询。

您可以通过创建查询过滤来优化查询返回的文档设立。查询过滤是一个表达式,用于指定MongoDB在读取或写入操作中用于匹配文档的搜索条件。要创建MongoDB查询筛选器,请使用 Hibernate Query Language (HQL) 或 Jakarta Persistence Query Language (JPQL) 语句。

提示

要学习;了解有关 HQL 和 JPQL 语法的详情,请参阅 Hibernate ORM 文档中的 Hibernate 查询语言指南 。

注意

查询支持

MongoDB Extension for Hibernate ORM 不支持所有MongoDB和 Hibernate查询功能。要学习;了解详情,请参阅“功能兼容性”页面上的 查询支持

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;
@Entity
@Table(name = "movies")
public class Movie {
@Id
@ObjectIdGenerator
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;
}
}

要学习;了解如何创建使用MongoDB Extension for Hibernate ORM 与此MongoDB示例集合交互的Java应用程序,请参阅入门教程。

重要

持久性上下文

启用Hibernate ORM 能够与数据库交互,您必须使用 Hibernate Session 或 Jakarta Persistence EntityManager 在持久性上下文中运行操作。使用 HQL 定义会话查询,使用 JPQL 定义实体经理查询。

Before running the examples in this guide, ensure that you add persistence context and transaction management code to your application that resembles the following code:

var sf = HibernateUtil.getSessionFactory();
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
// ... Perform CRUD operations here
tx.commit();
session.close();
sf.close();

要使用会话,您必须创建一个配置HibernateUtil.javaSessionFactory 文件。要学习;了解更多信息,请参阅入门教程中的配置应用程序步骤。

// 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;

要使用 EntityManager,您必须创建一个声明持久性单元的 persistence.xml文件。要学习;了解更多信息,请参阅 Hibernate ORM 文档中的使用 JPA 标准 API 的教程

要查询MongoDB数据,请在会话或实体经理上调用 createQuery() 方法。然后,在 Hibernate Query Language (HQL) 或 Jakarta Persistence Query Language (JPQL)声明中指定匹配条件。

本节介绍如何执行以下查询操作:

要从集合中检索所有文档,请将基本 select声明传递给 createQuery() 方法。在此声明中,指定表示要查询的集合的实体。

The following example retrieves the title values of all documents from the sample_mflix.movies collection by querying the Movie entity:

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?
...

要检索匹配特定条件的文档,请将带有 where 子句的 SELECT声明传递给 createQuery() 方法。在此声明中,指定表示要查询的集合的实体以及匹配条件。

The following example retrieves documents that have a title value of "Romeo and Juliet" from the sample_mflix.movies collection:

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

要检索匹配特定条件的单个文档,请将 getSingleResult() 方法链接到 createQuery() 方法。

The following example retrieves a single document that has a title value of "Best in Show" from the sample_mflix.movies collection:

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

重要

NonUniqueResultException 错误

如果查询匹配多个文档,则getSingleResult() 方法会引发NonUniqueResultException 错误。要避免此错误,请确保查询仅匹配一个文档或将查询结果限制为一个文档。

您可以使用 Jakarta Persistence Criteria API 以编程方式构建类型安全的查询,而不是使用 HQL 或 JPQL 声明创建查询筛选条件。

要使用 Criteria API 创建查询,请执行以下操作:

  1. 从会话或实体管理器创建 CriteriaBuilder对象。

  2. 从构建器创建一个 CriteriaQuery对象,并指定要查询的实体。

  3. 使用 CriteriaQuery 类提供的查询方法来指定查询条件。

提示

要学习;了解有关 Criteria API 的更多信息,请参阅 Jakarta EE 文档中的使用 Criteria API创建查询。

The following example uses the Criteria API to retrieve all documents that have a year value of 1925 from the sample_mflix.movies collection:

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

要运行Hibernate ORM 扩展当前不支持的MongoDB查询,您可以将查询作为MongoDB查询语言 (MQL)声明传递给 createNativeQuery() 方法。

要学习;了解如何运行原生查询,请参阅执行原生查询指南。

本节介绍如何使用操作符创建以下类型的查询筛选器:

提示

本节并未介绍所有可用的查询操作符。要查看查询操作符的完整列表,请参阅 Hibernate ORM 查询指南中的操作符表达式

注意

Hibernate ORM 扩展不支持所有比较操作符,包括LIKEBETWEEN 。要学习;了解有关支持限制的更多信息,请参阅“功能兼容性”页面上的“查询支持”。

您可以在查询声明中使用以下操作符字段值与指定的查询值进行比较:

  • =:等值匹配

  • <>:不等式匹配

  • >:大于比较

  • >=:大于或等于比较

  • <:小于比较

  • <=:小于或等于比较

The following example retrieves documents that have a year value greater than or equal to 2015 from the sample_mflix.movies collection:

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
...

您可以在查询语句中使用以下操作符来组合多个查询条件:

  • and:匹配所有条件

  • or:匹配任何条件

  • not: Invert criteria

The following example retrieves a document that has a title value of "The Godfather" and a year value of 1972 from the sample_mflix.movies collection:

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

本节介绍如何通过以下方式修改查询结果:

您可以在查询声明中使用 order by 子句,按指定字段的值对查询结果进行排序。默认下,order by 子句按升序对文档进行排序。要按降序对文档进行排序,请将 desc 关键字附加到字段名称。

The following example retrieves matching documents from the sample_mflix.movies collection and sorts them by the year field in descending order:

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

您可以通过将 setFirstResult() 方法链接到查询来跳过查询结果中指定数量的文档。将要跳过的初始文档数作为参数传递给此方法。

The following example runs the same query as the preceding example but skips the first matching document in the results:

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

您可以通过将 setMaxResults() 方法链接到查询来限制查询返回的文档数量。将要返回的最大文档数作为参数传递给此方法。

The following example runs the same query as the sort example but returns up to two matching documents in the results:

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

或者,可以在 HQL 或 JPQL声明中使用 limit 子句来限制查询返回的文档数量,如以下代码所示:

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();

本节介绍如何对以下字段运行查询:

要根据 ObjectId 值检索文档,如果使用会话,可以将此值作为参数传递给 get() 方法;如果使用实体经理,则可以将此值作为参数传递给 find() 方法。

The following example retrieves a document from the sample_mflix.movies collection by its ObjectId value:

var movieById = session.get(Movie.class, new ObjectId("573a13a8f29313caabd1d53c"));
var movieById = entityManager.find(Movie.class, new ObjectId("573a13a8f29313caabd1d53c"));

您可以通过创建 @Struct 聚合可嵌入对象来表示MongoDB嵌入式文档。您无法对单个可嵌入值创建查询筛选条件,但可以使用 Hibernate ORM 扩展来获取与特定父实体关联的 @Struct 聚合可嵌入值。

提示

要学习;了解有关表示嵌入式文档的更多信息,请参阅创建实体指南中的嵌入式数据

重要

查询限制

要学习;了解有关嵌入式查询限制的更多信息,请参阅“功能兼容性”页面上的 Hibernate 查询支持

The following example retrieves documents that have a title value of "Hairspray" from the sample_mflix.movies collection. Then, the code fetches the awards field, which stores the Awards @Struct aggregate embeddable, and prints the wins field of the Awards embeddable type:

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

Hibernate ORM 扩展支持以下用于查询数组字段的函数:

  • array_contains():匹配大量字段包含指定值的文档

  • array_contains_nullable():匹配数组字段包含指定值(包括 null 值)的文档

  • array_includes():匹配数组字段包含另一个数组值的文档

  • array_includes_nullable():匹配大量字段包含另一个大量值(包括 null 值)的文档

提示

要学习;了解有关大量函数的更多信息,请参阅 Hibernate ORM 用户指南中的用于处理数组的函数

The following example uses the array_contains() function to retrieve documents that have the value "Kathryn Hahn" in the cast array field from the sample_mflix.movies collection:

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

要了解有关对MongoDB数据执行其他操作的更多信息,请参阅CRUD 操作指南

要学习;了解有关使用 HQL 和 JPQL运行查询的更多信息,请参阅 Hibernate ORM 文档中的 Hibernate 查询语言指南。

后退

增删改查操作

在此页面上