193 lines
7.4 KiB
Plaintext
193 lines
7.4 KiB
Plaintext
= Hibernate 6.0 Final
|
|
Steve Ebersole
|
|
:awestruct-tags: ["Hibernate ORM"]
|
|
:awestruct-layout: blog-post
|
|
:docs-url: https://docs.jboss.org/hibernate/orm/6.0
|
|
:javadocs-url: {docs-url}/javadocs
|
|
:migration-guide-url: {docs-url}/migration-guide/migration-guide.html
|
|
:user-guide-url: {docs-url}/userguide/html_single/Hibernate_User_Guide.html
|
|
:jakarta-transformer-url: https://github.com/eclipse/transformer
|
|
|
|
It has been years in the making, but ORM 6.0 Final has finally been released!
|
|
|
|
This announcement will discuss the major changes as well as give insight into why
|
|
certain choices were made.
|
|
|
|
We will also be following up with a series of more focused posts targeting specific
|
|
improvements or cool new features. Stay tuned!
|
|
|
|
|
|
[[api-spi]]
|
|
== APIs and SPIs
|
|
|
|
While many things have changed in 6.0, we strove to minimize changes to APIs to help
|
|
mitigate migration costs.
|
|
|
|
[NOTE]
|
|
====
|
|
See https://hibernate.org/community/compatibility-policy/ for a discussion of what we consider
|
|
an API versus an SPI.
|
|
====
|
|
|
|
Applications which use only the Jakarta Persistence APIs will be source compatible within the
|
|
discussion in <<jpa>>.
|
|
|
|
Applications using Hibernate APIs will generally be bytecode and source compatible, aside
|
|
from the removal of deprecated stuff. There are a few one-off changes that break bytecode and/or
|
|
source compatibility; these are covered in the link:{migration-guide-url}[migration guide].
|
|
|
|
One specific change to note is that many of these contracts have been better defined with type
|
|
parameters. Theses where inconsistently and sometimes poorly defined in previous versions.
|
|
|
|
Quite a few SPI contracts have changed to support many of the topics discussed here as well as in
|
|
the link:{migration-guide-url}[migration guide]. Many will also be the subject of the mentioned
|
|
follow-up posts.
|
|
|
|
|
|
[[jpa]]
|
|
== Jakarta Persistence
|
|
|
|
Java Persistence has become Jakarta Persistence as part of the overall move of Java EE
|
|
to Jakarta. Various legal requirements forced the changing of the `javax` namespace -
|
|
for persistence, that means changing from `javax.persistence` to `jakarta.persistence`
|
|
for package names as well as property and hint names.
|
|
|
|
This is clearly an unfortunate and invasive change, but beyond our control. Luckily Jakarta
|
|
have developed a link:{jakarta-transformer-url}[transformer] to help with these migrations. We actually
|
|
used this tool to migrate Hibernate's own source code. It works well-ish.
|
|
|
|
For those using Maven, you are in luck (well, within the bounds of actually using Maven) in that
|
|
Jakarta themselves provide a Maven plugin to integrate this transformer.
|
|
|
|
For those using Gradle, you can use the tasks we developed to transform Hibernate's source code.
|
|
|
|
There is also a command-line form. See the link:{jakarta-transformer-url}[transformer] docs for details.
|
|
|
|
|
|
[[read-by-position]]
|
|
== Read-by-position
|
|
|
|
A few years ago, around the 5.4 timeframe, we worked with the amazing performance team at Red Hat
|
|
to squeeze even more great performance out of Hibernate ORM.
|
|
|
|
This work was part of a larger effort to improve the performance of WildFly. Ultimately, the limiting
|
|
factor to additional improvements within Hibernate was our approach of reading values from a JDBC
|
|
`ResultSet` by name rather than by position. For every JDBC driver out there, reading by name is slower.
|
|
|
|
It quickly became obvious that minimal changes would not be enough, and so this work led to many changes.
|
|
A great analogy is to consider migrating a Map-based solution to List-based. There is the obvious impact
|
|
of changing calls to accept an `int` rather than a `String` as well as internally keeping track of the
|
|
positions of each selected value within the `ResultSet`. There is also the perhaps not-so-obvious
|
|
impact of changing the callers and consumers of those contracts to keep track of positions.
|
|
|
|
These changes have led to improvements on a number of fronts:
|
|
|
|
1. As mentioned, reading by position is significantly faster than reading by name which leads to
|
|
performance improvements.
|
|
2. Historically Hibernate generated SQL select queries with a defined pattern of named column aliases
|
|
which were later used to access the specific result. We've all seen these "ugly" aliases. With these
|
|
changes, those select-clause aliases are no longer needed resulting in much more readable generated
|
|
SQL.
|
|
3. Although we implemented some improved support for limiting needed joins within an entity mapping
|
|
(joined inheritance, secondary tables) in 5.x, 6.0 allows even better opportunity for this. In
|
|
fact, the support for this in 5.x was conceptually back-ported from the 6.0 work.
|
|
4. (2) and (3) combined results in much smaller SQL needing to be sent to the server which can
|
|
have an impact on network communication. Every bit helps.
|
|
|
|
This was by far the biggest force behind 6.0 initially.
|
|
|
|
|
|
|
|
[[mapping-model]]
|
|
== Mapping Model
|
|
|
|
The mapping model is an SPI and as such will not be seen by all users. But
|
|
it is a major development and impacts many users providing extensions.
|
|
|
|
The main driving force behind this mapping model work was <<read-by-position>>,
|
|
and we had a number of design goals in developing it:
|
|
|
|
- support positional processing of attributes
|
|
- make it object-oriented
|
|
- make it user friendly
|
|
|
|
This model can be accessed though
|
|
link:{javadocs-url}/org/hibernate/engine/spi/SessionFactoryImplementor.html#getRuntimeMetamodels()[`RuntimeMetamodelsImplementor`]
|
|
which provides access to both:
|
|
|
|
- The Jakarta Persistence model : link:{javadocs-url}/org/hibernate/metamodel/spi/RuntimeMetamodelsImplementor.html#getJpaMetamodel()[`JpaMetamodelImplementor`]
|
|
- Hibernate's mapping model : link:{javadocs-url}/org/hibernate/metamodel/spi/RuntimeMetamodelsImplementor.html#getMappingMetamodel()[`MappingMetamodelImplementor`]
|
|
|
|
|
|
[[annotations]]
|
|
== Annotations
|
|
|
|
- type-safety
|
|
- `SqlTypes` - extension to `java.sql.Types`
|
|
|
|
|
|
[[query]]
|
|
== Query API
|
|
|
|
- Parameter binding
|
|
- `Session#createSelectionQuery`
|
|
- `Session#createMutationQuery`
|
|
- others???
|
|
|
|
|
|
[[sqm]]
|
|
== Semantic Query Model
|
|
|
|
Hibernate's Semantic Query Model (SQM) is its semantic representation of HQL
|
|
and Criteria queries. HQL is interpreted into SQM; Hibernate's Criteria
|
|
implementations are SQM nodes.
|
|
|
|
6.0 implements quite a few changes shared between HQL and Criteria. Most of
|
|
these are covered in link:{user-guide-url}#query-language[HQL] and
|
|
link:{user-guide-url}#criteria[Criteria] chapters of the User Guide.
|
|
|
|
Some specific changes include
|
|
|
|
- Automatic de-duplication of single entity results in a Query. See the link:{migration-guide-url}#query-sqm-rows[Migration Guide] for details
|
|
- Set operations (union, intersect, except)
|
|
- Set aggregations (listagg, e.g.)
|
|
- Window operations (over, e.g.)
|
|
- Vastly improved function support. See the link:{user-guide-url}#hql-exp-functions[User Guide] for details.
|
|
- ILIKE operator
|
|
- Improved temporal support (arithmetic, etc)
|
|
|
|
|
|
[[hql]]
|
|
== HQL
|
|
|
|
Previous versions of Hibernate used Antlr 2 for parsing. 6.0 updates to Antlr 4 for a few reasons:
|
|
|
|
- Antlr 2 is no longer supported, and has not for years
|
|
- Antlr 4 is faster than Antlr 2
|
|
- Antlr 4 grammars are easier to maintain, while the previous Antlr 2 grammars were poorly defined (largely as a function of Antlr 2 itself) and difficult to maintain.
|
|
|
|
|
|
|
|
[[criteria]]
|
|
== Criteria
|
|
|
|
- removal of legacy Criteria
|
|
- no longer Criteria -> HQL -> Query
|
|
- `hibernate.criteria.copy_tree` (performance)
|
|
- improved handling of parameter vs. literal
|
|
|
|
|
|
|
|
|
|
[[sql-ast]]
|
|
== SQL as AST
|
|
|
|
mention Dialect involvement
|
|
|
|
|
|
[[dialect-init]]
|
|
== Dialect initialization
|
|
|
|
- `Dialect` constructor
|
|
- `Dialect#initializeFunctionRegistry`
|