[hibernate-dev] 6.0 - Type system

Vlad Mihalcea mihalcea.vlad at gmail.com
Mon Jan 23 08:00:27 EST 2017


Hi,

Related to your questions:

he main thing I wonder about is what we mean by "custom
> types" in terms of what exactly is being customized?  And how does that
> relate specifically to BasicType versus EmbeddedType versus ...?


Most of the time, the users want to take advantage of various database
types that are not universally supported by all RDBMS: JSON, Money (SQL
Server).

On the Java side, I don't see what we can customize because we already
provide all the basic types, and for everything else, users can compose
those into Embeddables. The Java 1.8 Date/Time are an example of what users
would like to customize in case we didn't support this already. But even if
Java 1.9 adds other basic types, chances are that we are going to support
them natively, meaning that users will still not need to add a custom Type.

So, I don't see how a Hibernate user will customize the way Embeddables,
Enums, Entities or Collections are being stored or loaded from the
database. The exception to the rule is a recent Pull Request from someone
who wants to support PostgreSQL arrays. But this falls back into the same
category as before: database types that are not universally supported by
all RDBMS.

Vlad

On Thu, Jan 19, 2017 at 9:55 PM, Vlad Mihalcea <mihalcea.vlad at gmail.com>
wrote:

> There's a lot to dig in here. I'll have to get the branch and study the
> changes, to come back with some opinions.
>
> Vlad
>
> On Thu, Jan 19, 2017 at 7:34 PM, Steve Ebersole <steve at hibernate.org>
> wrote:
>
>> We are getting pretty far along on the 6.0 changes and I wanted to start
>> a(nother) discussion about Types in 6.0 to get feedback and thoughts on a
>> few topics.
>>
>> First a quick break down of JavaTypeDescriptors, SqlTypeDescriptors, Types
>> and "persisters"...
>>
>> (a lot of this is the same from pre-6.0, just making things more explicit)
>>
>> JavaTypeDescriptors and SqlTypeDescriptors are the "lowest level", so
>> let's
>> start there.  A JavaTypeDescriptor is a descriptor of a given Java type.
>> That is, it provides Hibernate with information about the Java type.  Is
>> it
>> a numeric type?  How do we compare 2 values of this type?  How do we make
>> a
>> deep copy of a value of this type?  Etc.  SqlTypeDescriptor is the same,
>> but for a database type (VARCHAR, BLOB, etc).  These 2 work together to
>> perform reading and writing at the JDBC-level.
>>
>> We decided to broadly categorize JavaTypeDescriptors based on the JPA type
>> categorizations:
>>
>>    1. BASIC - BasicJavaDescriptor
>>       1. TemporalJavaDescriptor
>>       2. NumericJavaDescriptor
>>    2. MANAGED - ManagedJavaDescriptor
>>       1. EMBEDDABLE - EmbeddableJavaDescriptor
>>       2. IDENTIFIABLE - IdentifiableJavaDescriptor
>>          1. MAPPED_SUPERCLASS - MappedSupercassJavaDescriptor
>>          2. ENTITY - EntityJavaDescriptor
>>
>>
>> Type (org.hibernate.type.spi.Type) represents a combination of a
>> JavaTypeDescriptor and one or more SqlTypeDescriptors in relation to a
>> specific "non-root Navigable domain value".  Navigable is a query-focused
>> contract (SQM/HQL/Criteria) so I wont get too deep into that here.  At a
>> high-level t is similar to JPA's Bindable except that it applies to
>> Collection indices (or map-keys) and elements (or map-values) as well.
>> Navigable essentially represents an named navigation one can perform in a
>> query.  The root Navigable is always an entity (EntityPersister).
>> EntityPersister is the only Navigable that does not expose a Type.  (There
>> is an EntityType, but it represents entity-valued non-root Navigables such
>> as a ManyToOne).  All other navigables expose a Type.  That is all a
>> long-winded way to say that Types represents that Java/SqlTypeDescriptors
>> for a role-based Navigable.
>>
>> Like the categorization discussed above for JavaTypeDescriptor, Type has a
>> similar categorization:
>>
>>    1. Type
>>       1. BasicType
>>          1. TemporalType
>>       2. AnyType
>>       3. ManagedType
>>          1. EmbeddedType
>>          2. IdentifiableType
>>             1. MappedSuperclassType
>>             2. EntityType
>>
>> It is important to keep in mind that these represents a specific reference
>> to thse things in regards to a Navigable.  E.g. an EntityType is the
>> "type"
>> of a SingularPersistentAttribute that is a ManyToOne - it points to the
>> corresponding EntityPersister but it also represents the FK columns to
>> refer to the entity.  It is a role-based Navigable.
>>
>> Historically reads and writes have all routed through the Type (with
>> certain Types delegating much of that to persisters).  That will no longer
>> be the case in 6.0 as one of the main design goals for 6.0 is to re-write
>> how Hibernate reads and writes (mainly reads) values from JDBC.  The major
>> shift here is to read all values from JDBC using a "SqlSelectionReader"
>> equivalent to a BasicType.  These values are read and held in an array
>> that
>> "readers" then know how to access (positionally) and use.  Most of that
>> design is beyond the discussion here, but it useful to understand.  It is
>> discussed in the design.adoc in my orm-sqm poc repo for those curious.
>> Long story, short... Types no longer directly implement JDBC read/write
>> which we will come back to later.
>>
>> PersistentAttribute and the other Navigables now take a role in JDBC
>> reads/writes.  AttributeConverters and other read/write-related concerns
>> have been moved to these contracts.  Again, most of this is covered in the
>> mentioned design doc.
>>
>> Since Type no longer directly implements JDBC read/write operations I
>> think
>> it is important to ask ourselves what exactly we see as "customizable" wrt
>> each Type.  Is that different for each category, or the same across all
>> Type categories?  E.g. I know of no customization of EntityType as it
>> exists in 5.x, and tbh I am not even sure what that would mean.  BasicType
>> obviously has some parts that we want to allow users to override, but is
>> that really best achieved through a custom BasicType?  Or is it better
>> served by allowing custom JavaTypeDescriptor/SqlTypeDescriptor and/or
>> SqlSelectionReader?  What about EmbeddedType?  CollectionType?  This would
>> affect @TypeDef and Type registration methods specific to customizations.
>>
>> Persisters for the most part continue to serve the same role they have in
>> the past with a few additions and some changes...
>>
>> One addition was the creation of an EmbeddedPersister.  *Embedded*.  This,
>> like CollectionPersister, models a "role" e.g. "Person.name" as opposed to
>> the Embeddable Name.class.  Note however that JPA calls it an
>> EmbeddableType and expects info about the Embeddable (the Class).
>> EmbeddedPersister is role-based (Embedded) instead, which is a mismatch.
>> In the case there are more than 1 usage of the Embeddable in different
>> Embedded roles then we have to decide which EmbeddedPersister to return.
>> It affects the sub-Attributes information.  We could just return "one of
>> them" and deal with it for Alpha1, but we should answer what we want to do
>> there long term.
>>
>> Collectively, these persisters now implement the JPA ManagedType model
>> directly.  Another addition was the creation of ManagedTypeImplementor,
>> IdentifiableTypeImplementor and MappedSuperclassTypeImplementor in the
>> persister hierarchy.  Which means we can now directly return them in our
>> JPA Metamodel impl.
>>
>> That also means implementing JPA's notion of Attributes.  I also needed
>> something similar for SQM's Navigable contract.  Plus I have been working
>> towards changing how Hibernate understands Attributes internally
>> (encapsulation - OO ftw!) for some time anyway, so this all dove-tailed
>> well.
>>
>> There are some things we should discuss too in terms of user impact.  We
>> know up front that we need to move to reading values from JDBC ResultSets
>> positionally, as opposed to nominally which is how it was exposed in
>> Hibernate prior to 6.0.  So we know already we will be asking implementors
>> and consumers of those contracts to make changes.  Given that, we have
>> *some* liberty in changing these contracts some more.  We just want to be
>> cognizant of (a) how much we change, (b) who it affects (use cases) and
>> (c)
>> whether there are alternatives.  For any use cases we determine to be
>> "valid" use cases, I think we need to make certain that there is some way
>> to handle that in the new alternatives.
>>
>> One use case, e.g., is setting Query parameters and being able to specify
>> its Type.  To a degree we want to be able to continue to support that.
>> But
>> I think we limit it to just references to org.hibernate.type.Type (though
>> "gutted") specifically and remove all others; and temporarily have the new
>> org.hibernate.type.spi.Type interface extend the old.  This would allow
>> them to continue to get these org.hibernate.type.Type references in some
>> fashion and use them as Query parameter type hints.  But I think we should
>> look at implementing some other parameter type "hints" like accepting
>> PersistentAttribute/Navigable references, JPA (static) metamodel
>> references, etc.  These are better, as they would include things like
>> AttributeConverter whereas the Type reference would not.
>>
>> Sorry this got so long.  I've had a lot floating around in my head the
>> last
>> few days as I have worked on 6.0 and I wanted to bring them up for
>> discussion.  The main thing I wonder about is what we mean by "custom
>> types" in terms of what exactly is being customized?  And how does that
>> relate specifically to BasicType versus EmbeddedType versus ...?
>> _______________________________________________
>> hibernate-dev mailing list
>> hibernate-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>>
>
>


More information about the hibernate-dev mailing list