Metadata binding #5998
Replies: 2 comments 9 replies
-
Hey, I think this goes in the direction we discussed a few days ago, so I don't have much to add except minor details.
I know this is in flux and there's enough work already, so I'm not asking for the plan right now but more potentially, in the medium term. Is this intended to be generic and potentially used by other projects (like HCANN was), or to stay in ORM forever and potentially have ORM-specific bits? I'm not counting the HCANN/Jandex implementations as ORM-specific, as those could work for other projects as well. I'm asking because this seem similar to work we did in HSearch (though there's no concept of package in HSearch, and we don't differentiate fields/methods, there's just properties). I feel we often have similar needs and might benefit from merging our code at some point in the future, be it only to ensure consistent behavior when interpreting annotations in both projects. Another reason for merging would be complexity: believe it or not, some of the type resolution stuff can be relatively complex and while HCANN is able to do it to some extent (not sure how well), Jandex is not, to the best of my knowledge (nor should it, IMO). That being said, having a separate implementation in each project does have its merits, too. I remember HCANN causing release headaches and getting in the way of swift changes when you had to handle... records, I believe? A problem you wouldn't have if your abstraction was inside ORM. And, of course, there's the topic of backwards compatibility that you wouldn't need to worry about with internal code.
I'm a bit surprised by that, shouldn't this model be independent of annotation-based mapping? Or maybe I misunderstood; do you intend to use |
Beta Was this translation helpful? Give feedback.
-
Not meaningt to make this even more intertwined, but there might be an opportunity for an additional "nice to have" regarding:
It would be great if the internal contracts were able to ensure that reliance on reflection and annotation reading, and indeed using external libraries for such purposes, was forcibly restricted to happen only during the bootstrap phases during which it's necessary. As an example, I know we had a couple of corner cases in which reflection/annotations/HCANN were being relied upon at runtime (after bootstrap has completed). I'm not sure if we still have such corner cases (it's possible we do, but I don't recall of concrete examples so I'm not certain); what I'm suggesting is that it would be beneficial if the internal Metadata binding contract could somehow help to prevent such uses at runtime. In practice this would imply that in frameworks like Quarkus (in which the metadata building aspect is potentially run on a different JVM than the one using the generated metadata at runtime) that dependencies such as HCANN could be omitted from the runtime dependencies. Also, this could lead to reducing the amount of reflection metadata necessary for GraalVM. N.B. this would be a nice to have, but less so important than the other goals that @sebersole already listed. |
Beta Was this translation helpful? Give feedback.
-
https://hibernate.atlassian.net/browse/HHH-16114
https://github.com/sebersole/hibernate-annotation-source
NOTE: Much of this is based on the older https://github.com/sebersole/hibernate-orm/tree/jandex-binding branch
This is discussion about binding metadata sources (annotated classes and xml) into the
org.hibernate.mapping
"boot model". More specifically, this is about what we currently call "annotation binding" to differentiate it fromhbm.xml
binding even though "annotation binding" also includes handling oform.xml
files.There are a few moving and inter-related parts to this proposal.
As a background, annotation binding currently uses HCANN to process the annotations along with its
MetadataProvider
hook to applyorm.xml
metadata. To be clear, HCANN itself does not do anything related to the xml - ORM itself does all of that via the hook. It also eagerly uses reflection.So a few (inter-related) goals -
Annotation
.Although not a direct goal, all this work also presents the possibility for a potential simplified model for "additional mapping" info as used by Envers, Hibernate Search, etc. At the moment, these providers are forced to use JAXB model based on
hbm.xml
At a high-level, the proposal is for a multi-step process for binding - from
source
->intermediate
->boot
. I have a PoC thatsource
model, as well as building one from both HCANN and reflectionintermediate
, as well as transformation fromsource
The PoC does not yet build the
boot
model, though a previous Jandex PoC defines much of that using very similar model and approach.Metadata Source
At the "lowest level" in this processing we have abstractions for handling "reflection" information as well as "annotations".
Abstraction for
Annotation
https://hibernate.atlassian.net/browse/HHH-15996
This is proofed already. It is largely based on 2 contracts -
AnnotationDescriptor
which describes aspects of the annotation class (is it repeatable, etc)AnnotationUsage
which is a particular usage of a givenAnnotationDescriptor
. This correlates toAnnotation
An ancillary contract is
AnnotationTarget
which exposes access toAnnotationUsage
references from a "target" (package, class, field, ...)Abstraction for
Class
https://hibernate.atlassian.net/browse/HHH-16012
This is also proofed already and is defined by -
PackageDetails
ClassDetails
FieldDetails
MethodDetails
which all act as
AnnotationTarget
.This step alleviates the reliance on reflection (it is targeted reflection abstraction) and supports dynamic models. It also acts as an abstraction for the sources of these details (HCANN, Jandex, etc) and therefore supports migration between these sources.
This model is designed as an abstraction over reflection to support dynamic models, as well as Hibernate's generalized
entity-name
feature which might map a single class with multiple names.This model is one potential solution for "additional mapping" info.
Binding
Binding here is defined as the process of creating the
org.hibernate.mapping
references.Currently this happens via complicated static calls that stash details in various Maps as intermediate steps. The proposal is to create an actual intermediate model that is a generalized categorization of the model.
Intermediate Model
When I say "generalized categorization" this means that we understand that one
ClassDetails
represents an entity while another represents a converter e.g.This is where my PoC currently stands so this is very much in flux. But at the moment, we have:
EntityHierarchy
EntityTypeMetadata
EmbeddableTypeMetadata
AttributeMetadata
ConversionMetadata
AttributeOverrideMetadata
AssociationOverrideMetadata
These contracts also expose the underlying "source" model parts for access to
AnnotationUsage
, etc. where appropriateCurrently, the understanding of the categorization of an attribute (basic, embedded, etc) is simply an enum. Largely an implementation detail, but important to note.
This model also performs some basic interpretation such as resolving mapping inheritance type, hierarchies, caching, etc
This model is another potential solution for "additional mapping" info.
Boot Model
Here, boot model is the
org.hibernate.mapping
model which is ultimately the target for processing mapping sources.We'd build this boot model using the intermediate model along with its underlying source model.
This part is still largely undefined in my PoC. I have most of
RootClass
binding done aside from attributes.Beta Was this translation helpful? Give feedback.
All reactions