[hibernate-dev] 6.0 - Type redesign

Emmanuel Bernard emmanuel at hibernate.org
Fri Jul 22 05:14:45 EDT 2016


The good news is that I am following you :D

I think one of the option is some API to which you can pass the (JPA)
Type, a Path from root and it would return a structure qualifying the
embedded info and not just the embeddable.

I'm making things up here

//might not even need the type, could be guessed from the Path?
AttributeMapping am = mappingProvider.forPath(path);

What's nasty is that it then requires two parallel APIs, or rather it
would not flow from an enhanced JPA type API.

An alternative would be what I think you propose with the BindableType,
that is an extension point that describes the specifics of the
specialization when navigating from one node type to another. I think.

An alternative that I can think of is as follows. I'm assuming that the
data that needs to be contextualized by the path is mapping in nature or
at least not at all represented in the JPA types.
Each (JPA) type instance would be inherently specific to the path it
comes from. It would keep exposing the JPA non contextualized info but
also add contextualized info.

HibernateEntityType<Foo> fooModel =
  (HibernateEntityType<Foo>) entityManagerFactory.getMetamodel().entity(Foo.class); // considered a root for navigation

for (HibernateSingularAttribute sa : fooModel.getSingularAttributes()) {
   if (sa.getPersistentAttributeType() == EMBEDDED) {
       HibernateEmbeddableType et = (HibernateEmbeddableType) sa.getType();
       for (HibernateSingularAttribute esa : fooModel.getSingularAttributes()) {
           if (esa.getPersistentAttributeType() == BASIC) {
               int span = esa.getPhysicalInfo().getColumnSpan();
           }
      }
    }
}

Hopefully, JPA does not mandate == between different types.

A question I have is how navigable and easy such API would be for a
persister. But that's something to explore.

Emmanuel

On Thu 2016-07-21 21:10, Steve Ebersole wrote:
> Put another way, I think the problem (and probably the solution) here is
> similar to JPA's Bindable (and Path) concept.
> 
> On Thu, Jul 21, 2016 at 2:27 PM Steve Ebersole <steve at hibernate.org> wrote:
> 
> > One goal of the redesign is to build more friendly, easy-to-follow
> > contract for access to this metadata at runtime (legacy persister state).
> > Rather than accessing pieces of information pertaining to attributes across
> > many, many arrays I wanted an array of a composite representation of these
> > attributes.  JPA defines it this way, so on some level you'd think it would
> > be pretty straightforward to move this direction.  The major pain-point I
> > have been facing is that JPA does not define "mapping information" at all
> > in its Metamodel/Types.  The main place this comes to a head is
> > EmbeddableType, especially given access to it directly on Metamodel *by
> > class*.  In JPA terms that return has to model the Embeddable (no mapping
> > info) rather than the Embedded.  And then further when we
> > expose EmbeddableType's attributes we have the same problem continued
> > because the context/root is the embeddable rather than the embedded.
> > Hopefully this makes sense, but as an example consider (using a "component
> > safe NamingStrategy):
> >
> > @Entity
> > class Store {
> >     ...
> >     @Embedded
> >     Address headquartersAddress;
> >     @Embedded
> >     Address locationAddress;
> > }
> >
> > @Embeddable
> > class Address {
> >     String streetAddress;
> >     @Embedded
> >     PostalCode postalCode;
> >     ...
> > }
> >
> > @Embeddable
> > class PostalCode {
> >     String zip;
> >     String plus4;
> >     @ManyToOne
> >     City city;
> > }
> >
> > Then consider that JPA frames access to this information as:
> >
> > EmbeddableType<Address> addrType = metamodel.embeddable( Address.class );
> >
> > Because it is generic to the Address embeddable, we have no access to the
> > specific embedded mapping info.  And if we follow this access down further,
> > it also means the same for accessing the attributes of that EmbeddableType<Address>.
> > For example, accessing the "postalCode.zip" from the EmbeddableType<Address>
> > we'd have no ability to resolve whether that maps to "headquartersAddress_postalCode_zip"
> > or "locationAddress_postalCode_zip".  And of course, as an ORM we need
> > access to that mapping information :)
> >
> > Essentially that is the crux of the difficulty I have at the moment.
> >
> > I know we could get around this by splitting (or keeping split) the
> > notions of ORM Type and JPA Type, but I would like to avoid that : this
> > unification is going to be important to the SQM Criteria support.
> >
> > So the question becomes how to best handle exposing an "Attribute" with
> > mapping information as well as an "Attribute" without mapping information.
> >
> > I will be working on some proposals for ways to do this over the next week
> > or so.  And maybe y'all see a solution easier than I do (I fear I may not
> > be seeing the forest through the trees atm).
> >
> >
> > On Thu, Jul 21, 2016 at 7:49 AM Steve Ebersole <steve at hibernate.org>
> > wrote:
> >
> >> I am working on a larger response to some current challenges, but here is
> >> a quick response to your specific points...
> >>
> >> On Wed, Jul 20, 2016 at 12:50 PM Emmanuel Bernard <emmanuel at hibernate.org>
> >> wrote:
> >>
> >>>
> >>> BasicType does not handle multiple column and compositeType is the
> >>> mebedded case. How would multi-column types would be handled?
> >>>
> >>
> >> In terms of what exactly?  Assuming you mean access to the JDBC
> >> descriptors, that is still being determined.  At the moment there is no
> >> single Type-level access to this information.  Each specific Type
> >> sub-interface defines access differently.  I am not a fan of that that
> >> aspect.  The other approach is to define a plural form on Type
> >> (Type#getColumnMappings), and BasicType would just ensure that there is
> >> just one.
> >>
> >>
> >> Why do you need to ”unscope" the TypeConfiguration? What do you gain from
> >>> it? I’m trying to picture a reuse use case?
> >>>
> >>
> >> Functionally we do not gain anything.  I was just trying to be balanced.
> >> We injected the SF into the TypeConfiguration, I wanted to un-inject it as
> >> well for 2 reasons:
> >>
> >>    1. release the reference to the SF
> >>    2. prepare the TypeConfiguration for binding to another SF.
> >>
> >> The only use case I had in mind was tests where we occasionally build
> >> multiple SF instances from a single Metadata.
> >>
> >>
> >> Methods of Type needing Session: I used to call them passing null in some
> >>> old code and hoping for the best. Are the reasons for using Session still
> >>> present? Would be nice to get rid of that.
> >>>
> >>
> >> This is only ever needed (sometimes) from EntityType.  I guess it depends
> >> which specific method(s) you are asking about.  For some (reading, writing)
> >> yes I think we will continue to need the Session: it is used for access to
> >> JDBC as well as other needed interactions with the Session/PC (scheduling
> >> ids for batch load, etc).  For other methods, maybe not.
> >>
> >>
> >> On the genericization of Type, it would be extremely nice indeed for OGM,
> >>> but it would require to genericize SqlTypeDescriptor and its methods
> >>> essentially. Not necessarily super trivial.
> >>>
> >>
> >> I understand that.  It is not a primary goal for me tbh.  But if we can
> >> get a decent design for the ORM case and can see an easy way to extend this
> >> to OGM without negatively impacting ORM I am all for it.  Given the
> >> delegation to Binder and Extractor I think this will be doable, although I
> >> assume we will need some parameterized param object to make this work.  The
> >> paam object would give us access to "JDBC services" in ORM and something
> >> else in OGM.
> >>
> >>
> >>


More information about the hibernate-dev mailing list