[hibernate-dev] 6.0 - Type system

Christian Beikov christian.beikov at gmail.com
Mon Jan 23 12:10:48 EST 2017


Since custom JavaTypeDescriptors and SqlTypeDescriptors can be used 
instead, I'm also for removing it.

Am 23.01.2017 um 15:45 schrieb andrea boriero:
> trying to find a valid reason to keep UserType but not able, so I'm for
> removing it.
>
> On 23 January 2017 at 14:36, Vlad Mihalcea <mihalcea.vlad at gmail.com> wrote:
>
>> Hi,
>>
>> I see no reason why we should keep it indefinitely. I'd say we deprecate it
>> in 5.x, and remove it later (6.0 or 6.1).
>> Migrating a custom UserType to using Java and SQL descriptor is not
>> difficult, and we could just write a blog post for a step-by-step guide.
>>
>> Anyone in favor of keeping UserType?
>>
>> Vlad
>>
>> On Mon, Jan 23, 2017 at 4:11 PM, Steve Ebersole <steve at hibernate.org>
>> wrote:
>>
>>> Nice!
>>>
>>> So if we keep UserType, we have to be clear that it has to change.  I
>> also
>>> do not want to continue to support the other "user type extensions",
>> like:
>>>
>>>     1. org.hibernate.usertype.EnhancedUserType
>>>     2. org.hibernate.usertype.DynamicParameterizedType
>>>     3. org.hibernate.usertype.LoggableUserType
>>>     4. etc
>>>
>>> So we should come up with a plan for that.
>>>
>>>
>>> On Mon, Jan 23, 2017, 1:48 PM Vlad Mihalcea <mihalcea.vlad at gmail.com>
>>> wrote:
>>>
>>> Hi,
>>>
>>> I like the SqlTypeDescriptor and JavaTypeDescriptor much better than
>>> UserType, which we should probably deprecate in 6.0.
>>>
>>> I wrote an article on my blog in which I demonstrate how to create a JSON
>>> type using JavaTypeDescriptor and SqlTypeDescriptor:
>>>
>>> https://vladmihalcea.com/2016/06/20/how-to-map-json-objects-
>>> using-generic-hibernate-types/
>>>
>>> I like this example because it shows how you can reuse the same
>>> JavaTypeDescriptor for two different JSON SQL types: String or Binary,
>>> for which we have two distinct SqlTypeDescriptor objects.
>>>
>>> The new User Guide shows ho to implement Custom Types using the Java and
>>> SQL descriptors as well:
>>>
>>> http://docs.jboss.org/hibernate/orm/5.2/userguide/
>>> html_single/Hibernate_User_Guide.html#basic-custom-type
>>>
>>> Vlad
>>>
>>> On Mon, Jan 23, 2017 at 3:37 PM, Steve Ebersole <steve at hibernate.org>
>>> wrote:
>>>
>>> Right, and that exactly lines up with what I am proposing.
>>>
>>> If the intent of "customize" is to describe new Java types (e.g. Java 8
>>> temporals prior to our explicit support) the tht is the role of a
>>> JavaTypeDescriptor, specifically a BasicJavaDescriptor.  They would
>>> register a BasicJavaDescriptor describing the type.
>>>
>>> If the intent is to model a non-supported SQL type then that would mean
>>> adding a new SqlTypeDescriptor describing that type, although that will
>>> often also mean adding a new BasicJavaDescriptor describing the Java
>>> mapping of that SQL type.
>>>
>>>
>>> On Mon, Jan 23, 2017 at 7:00 AM Vlad Mihalcea <mihalcea.vlad at gmail.com>
>>> wrote:
>>>
>>> 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
>>>
>>>
>>>
>>>
>>>
>> _______________________________________________
>> hibernate-dev mailing list
>> hibernate-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>>
> _______________________________________________
> 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