Overview
在本指南中,您可以学习;了解如何使用MongoDB Extension for Hibernate ORM 在日期时间字段上调用 Hibernate Query Language (HQL) extract() 和 format() 函数。您可以使用 extract() 返回日期时间值的一部分,并使用 format() 将日期时间值呈现为字符串。
Hibernate ORM 扩展将每个调用转换为 $project 阶段中的MongoDB聚合表达式。您可以在 SELECT 子句中对日期时间字段调用任一函数。
注意
时区
Hibernate ORM 扩展在运行应用程序的Java虚拟机(JVM)的默认时区域中解析每个日期时间函数。它将该区域作为生成的操作符符的 timezone 参数传递给MongoDB 。在配置了不同时区的主机上,同一查询可能会返回不同的值。
由于 Hibernate ORM 扩展不支持将函数调用作为计算表达式的操作数,因此您无法将日期时间函数与算术操作符组合使用。要学习;了解更多信息,请参阅指定查询指南中的使用计算表达式部分。
样本数据
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.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; } }
学习如何创建使用 MongoDB Extension for Hibernate ORM 与此 MongoDB 示例集合交互的 Java 应用程序,请参阅 入门 教程。
本指南中的示例使用 Movie 实体的 released字段,其中存储了 Instant 值。
提取日期时间字段
您可以使用 extract() 函数返回日期时间值的特定部分,例如年、月或日。
extract(field from x) 函数返回日期时间值的单个字段。 Hibernate ORM 扩展支持以下 field 值:
字段 | MongoDB翻译 |
|---|---|
|
|
| 通过将 |
|
|
|
|
| 根据 |
| 根据 |
|
|
|
|
|
|
|
|
|
|
| 根据 |
| 根据 |
| 计算方式为自 Unix 纪元以来的整数秒数 |
以下示例返回 sample_mflix.movies集合中每部 "Hairspray" 电影的标题以及电影的发行年份:
var extractResult = session.createQuery( "select title, extract(year from released) as releaseYear from Movie where title = :title", Object[].class) .setParameter("title", "Hairspray") .getResultList(); for (var row : extractResult) { System.out.println("Title: " + row[0] + ", Release Year: " + row[1]); }
var extractResult = entityManager.createQuery( "select m.title, extract(year from m.released) as releaseYear from Movie m where m.title = :title", Object[].class) .setParameter("title", "Hairspray") .getResultList(); for (var row : extractResult) { System.out.println("Title: " + row[0] + ", Release Year: " + row[1]); }
Hibernate ORM 扩展将前面的查询转换为以下 $project 阶段,其中 America/New_York 是Java虚拟机(JVM)的默认时区域:
{ "$project": { "title": true, "releaseYear": { "$year": { "date": "$released", "timezone": { "$literal": "America/New_York" } } }, "_id": 0 } }
重要
星期编号
day of week字段返回MongoDB $dayOfWeek 值,该值从 1(星期日)到 7(星期六)对天数进行编号。这与Java DayOfWeek枚举不同,后者对从星期一的 1 到星期日的 7 之间的天数进行编号。
Hibernate ORM 扩展不支持date、time、offset、timezone_hour 和 timezone_minute 字段。提取不支持字段的查询会引发 FeatureNotSupportedException。
将日期时间格式化为字符串
format(x as pattern) 函数将日期时间值呈现为字符串。 Hibernate ORM 扩展会将调用转换为MongoDB $dateToString操作符,并将每个模式代码映射到等效的MongoDB格式说明符。您还可以以 format(x, pattern) 形式调用该函数,并直接传递MongoDB格式说明符。
Hibernate ORM 扩展支持以下模式代码:
模式代码 | 说明 | MongoDB说明符 |
|---|---|---|
| 四位数的年份 |
|
| 基于周的四位 ISO-8601 年份 |
|
| 两位数的月份 |
|
| 月份名称缩写 |
|
| 完整月份名称 |
|
| 两位数 ISO-8601 周编号 |
|
| 两位数的月份日期 |
|
| 年中的某一天 |
|
| 两位数的小时数,采用 24 小时制 |
|
| 两位数的分钟数 |
|
| 两位数秒数 |
|
| 三位数毫秒 |
|
| UTC 偏移量 |
|
MongoDB返回美国区域设置中的月份和日期名称。用单引号括起来的字符会传递到输出,而不会被解释为模式代码。
以下示例以 yyyy-MM-dd 字符串的形式返回每部 "Hairspray" 电影的标题及其发布日期:
var formatResult = session.createQuery( "select title, format(released as 'yyyy-MM-dd') as releaseDate from Movie where title = :title", Object[].class) .setParameter("title", "Hairspray") .getResultList(); for (var row : formatResult) { System.out.println("Title: " + row[0] + ", Release Date: " + row[1]); }
如果要改用MongoDB格式说明符,则可以以 format(released, '%Y-%m-%d') 的形式调用该函数。
var formatResult = entityManager.createQuery( "select m.title, format(m.released as 'yyyy-MM-dd') as releaseDate from Movie m where m.title = :title", Object[].class) .setParameter("title", "Hairspray") .getResultList(); for (var row : formatResult) { System.out.println("Title: " + row[0] + ", Release Date: " + row[1]); }
如果要改用MongoDB格式说明符,则可以以 format(m.released, '%Y-%m-%d') 的形式调用该函数。
Hibernate ORM 扩展将前面的查询转换为以下 $project 阶段:
{ "$project": { "title": true, "releaseDate": { "$dateToString": { "date": "$released", "format": { "$literal": "%Y-%m-%d" }, "timezone": { "$literal": "America/New_York" } } }, "_id": 0 } }
使用上表之外的模式代码的查询会抛出 FeatureNotSupportedException。这包括单字符和可变宽度代码,如 y、M、d、H、h、m、s 和 a,因为MongoDB没有等效的说明符。超过三个字符的重复时区域代码(例如 ZZZZZZZ)是不明确的,也会引发异常。
更多信息
要学习;了解有关创建查询筛选器和在查询语句中使用操作符的更多信息,请参阅“指定查询”指南。
要了解有关使用 HQL 和 JPQL 运行查询的更多信息,请参阅 Hibernate ORM 文档中的 Hibernate 查询语言指南。