Hibernate 6.0 最终版

发布者:    |       Hibernate ORM 发布

这一版本历时多年,ORM 6.0 最终版终于发布!

本公告将讨论主要变更,并深入探讨为何做出某些选择。

我们还将通过一系列更专注于特定改进或新特性的文章来跟进。敬请期待!

APIs 和 SPIs

虽然 6.0 版本中有很多变化,但我们努力最小化对 API 的更改,以帮助减轻迁移成本。

请参阅 https://hibernate.com.cn/community/compatibility-policy/ 了解我们认为的 API 与 SPI 的区别。

仅使用 Jakarta Persistence API 的应用程序将在 Jakarta Persistence 部分的讨论中保持源兼容性。

使用 Hibernate API 的应用程序通常在字节码和源代码上保持兼容性,但需要移除已弃用的内容。还有一些一次性更改会破坏字节码和/或源代码兼容性;这些内容在 迁移指南 中有所说明。

值得注意的是,许多这些合约都通过类型参数得到了更好的定义。在之前的版本中,这些定义通常不一致,有时还定义得不好。

许多 SPI 合约已更改,以支持在此处以及 迁移指南 中讨论的许多主题。其中许多也将是后续文章的主题。

Jakarta Persistence

Java Persistence 已成为 Jakarta Persistence,这是 Java EE 整体迁移到 Jakarta 的一部分。各种法律要求迫使更改了 javax 命名空间 - 对于持久性而言,这意味着将包名以及属性和提示名称从 javax.persistence 更改为 jakarta.persistence

这显然是一个不幸且侵入性的变更,但我们无法控制。幸运的是,Jakarta 开发了一个转换器来帮助这些迁移。我们实际上使用了这个工具来迁移 Hibernate 的源代码。它效果还不错。

对于那些使用 Maven 的人来说,你很幸运(好吧,在实际上使用 Maven 的范围内)因为 Jakarta 本身提供了一个 Maven 插件来集成这个转换器。

对于那些使用 Gradle 的人来说,你可以使用我们开发的用于转换 Hibernate 源代码的任务。

还有一个命令行形式。有关详细信息,请参阅转换器文档。

按位置读取

几年前,大约在 5.4 时期,我们与 Red Hat 令人惊叹的性能团队合作,从 Hibernate ORM 中挤出更多的出色性能。

这项工作是我们改进 WildFly 性能更大努力的一部分。最终,Hibernate 中进一步改进的限制因素是我们的从 JDBC ResultSet 中按名称而不是按位置读取值的做法。对于所有的 JDBC 驱动程序,按名称读取都较慢。

很快就很明显,最小的更改是不够的,因此这项工作导致了许多变化。一个很好的类比是将基于 Map 的解决方案迁移到基于 List 的。这显然会对调用从接受一个 String 而不是一个 int 进行更改产生影响,以及在内部分配跟踪每个选定的值在 ResultSet 中的位置。还有可能不那么明显的影响,即更改那些调用者和消费者合同以跟踪位置。

这些更改在多个方面带来了改进

  1. 如前所述,按位置读取比按名称读取要快得多,这导致了性能改进。

  2. 从历史上看,Hibernate 生成的 SQL 选择查询具有定义良好的命名列别名的模式,这些别名随后用于访问特定的结果。我们都见过这些“丑陋”的别名。随着这些更改,选择子别名不再需要,从而使生成的 SQL 更易于阅读。

  3. 尽管我们在 5.x 中实现了一些对实体映射中所需连接的限制的改进(联合继承、二级表),但 6.0 提供了更好的机会。实际上,5.x 中对这一功能的支持是从 6.0 的工作中概念上回滚的。

  4. (2) 和 (3) 结合起来,导致需要发送到服务器的 SQL 更小,这可能对网络通信产生影响。每一个比特都很重要。

这无疑是 6.0 初始阶段最大的推动力。

映射模型

映射模型是一个 SPI,因此并不是所有用户都能看到它。但这是一个主要的发展,影响了许多提供扩展的用户。

推动这一映射模型工作的主要动力是按位置读取,我们在开发它时有一些设计目标

  • 支持属性的位置处理

  • 使其面向对象

  • 使其用户友好

可以通过RuntimeMetamodelsImplementor访问此模型,它提供对两者的访问

注解

从历史上看,Hibernate 的注解直接从其 hbm.xml 映射中发展而来。这些旧注解与 XML 一样是基于 String 的,提供了 XML 的所有缺点,而没有注解的任何优点。

6.0 从类型安全的角度重新设计了 Hibernate 的注解,同时更好地利用了注解的优点。大多数也可以用作元注解。

映射基本值注释发生了最大变化。详细信息请参阅用户指南

嵌入式的映射也发生了变化。有关详细信息,请参阅用户指南。嵌入式现在支持构造函数注入

查询API

  • 参数绑定

  • Session#createSelectionQuery

  • Session#createMutationQuery

  • 其他???

语义查询模型

Hibernate的语义查询模型(SQM)是其对HQL和Criteria查询的语义表示。HQL被解释为SQM;Hibernate的Criteria实现是SQM节点。

6.0实现了HQL和Criteria之间的一些共享更改。其中大部分在用户指南的HQLCriteria章节中进行了介绍。

一些具体的更改包括

  • 查询中自动去重单个实体结果。有关详细信息,请参阅迁移指南

  • 集合操作(并集、交集、差集)

  • 集合聚合(例如listagg)

  • 窗口操作(例如over)

  • 大幅提高了函数支持。有关详细信息,请参阅用户指南

  • ILIKE运算符

  • 改进的时间支持(算术等)

HQL

Hibernate的前几个版本使用Antlr 2进行解析。6.0更新到Antlr 4,出于几个原因

  • Antlr 2不再受支持,并且已经多年不受支持

  • Antlr 4比Antlr 2快

  • Antlr 4语法更容易维护,而之前的Antlr 2语法定义不明确(很大程度上是Antlr 2本身的函数),难以维护。

Criteria

Hibernate的遗留Criteria API已经弃用多年,并在6.0中完全删除。现在仅通过Jakarta Persistence API及其扩展提供对Criteria查询的支持。

语义查询模型中所述,Hibernate的SQM模型是Jakarta Persistence Criteria节点API的实现。这在与之前版本相比提供了显著更好的性能。

6.0还增加了一个与Criteria性能相关的新设置 - hibernate.criteria.copy_tree。Jakarta Persistence规范要求对传递给EntityManager#createQuery的Criteria树进行复制。这显然会有性能影响,但这是出于安全考虑。hibernate.criteria.copy_tree允许Hibernate不复制树,从而提高性能。只需确保在调用#createQuery之后不要修改树。

SQL作为AST

6.0在将查询建模为树方面全面投入。我们上面讨论了这如何适用于HQL和Criteria查询,但我们现在也以树的形式建模SQL查询。

这有很多好处,但主要好处是直接涉及Dialect。树作为将AST转换为JDBC调用的API,允许Dialect在此过程中发挥更强大的作用。

Dialect初始化

在之前版本中,Dialect基本上是关于使用数据库的静态细节。这意味着Dialect实现不能结合特定版本偏差,这也是为什么Hibernate有这么多版本特定的子类。

6.0改变了Dialect创建的方式,使其能够根据使用的数据库/驱动程序的版本初始化自己。

@Incubating

6.0 版本还引入了一个新的 @Incubating 注解,目的是通知用户,某个特定合约在未来可能会发生变化。这些通常是新合约,我们可能需要根据额外的用例或对现有用例的澄清来更改它们。

把它想象成一种“自行承担风险”的警告。显然,我们会努力不更改这些合约,但这给了我们在需要时更改它们的灵活性,并向用户传达这种可能性。

有时设置被认为是孵化中的。这些在相应的 org.hibernate.cfg.AvailableSettings 字段上用 @Incubating 标记,并且还使用 org.hibernate.orm.incubating 类别进行日志记录。

我们还生成了一个文档 报告

发布工件

从 6.0 版本开始,我们将不再向 SourceForge 发布 zip 和 tgz 打包文件。

从 6.0 版本开始,我们现在发布额外的文档工件,例如

在未来几周内,我们还将重新评估以下内容

其中大部分内容要么过时,要么已被纳入其他地方。

结论

有关更多详细信息,请参阅

要取得联系,请使用在 网站上 讨论的正常渠道。


返回顶部