[hibernate-dev] [feature request][discuss] smoother serializers integration?

Steve Ebersole steve at hibernate.org
Thu May 4 09:50:59 EDT 2017


Oops, that (3) in previous reply should have read:
3. supporting each format creates a new "optional" library dependency

Overall, I like Christian's approach as a potential generalized approach to
this.  Basically a combination of

   1. a query used to provide the "view source values"
   2. some indication of how to map those "source values" to your view model


And again, I think 6.0's improved dynamic-instantiation queries are a
simple, already-built-in way to achieve that for most cases.  But I am open
to discussing a way to supply that combination via API if we deem that
would be good - although then I'd also question how the current
TupleTransformer does not meet that need.

On Thu, May 4, 2017 at 8:43 AM Steve Ebersole <steve at hibernate.org> wrote:

> Were there a standard "represent something in XML-ish format" contract
> portable across a number of formats (XML, JAXB, JSON, etc) then I'd be more
> inclined to agree with this.  But as it is, supporting this would mean
> Hibernate implementing multiple such contracts, one per format.  However,
>
>    1. these formats are not our core competency
>    2. maintaining a complete set of these transformers across all the
>    popular formats du-jour is a large undertaking
>    3. I am not convinced that
>
> All of these increase the technical risk.
>
> Additionally, to properly support this we'd really need the ability to
> then "map" multiple views for a given entity-graph-root.  What I mean by
> that, is that such DTO approaches often need multiple "views" of a given
> entity, e.g. a CompanyListDTO, CompanyOverviewDTO,
> CompanyDetailsGeneralDTO, etc for a Company entity.  The point of this is
> that
>
>    1. the transformers for these are specific to each DTO type and would
>    be applied per-transformation
>    2. were Hibernate to "provide" this for applications
>
> IMO the use of queries to obtain views is logical.  Populating each of
> those specific DTOs (CompanyListDTO, etc) in the most efficient way is
> going to require very different SQL for each DTO.  This implies some kind
> of "mapping" to be able associate each DTO with query.
>
> Given 6.0's improved dynamic-instantiation support, I even think that is a
> great solution as well *for most cases*.
>
> So, while my objection has a "practical impact" component, I also just
> question whether Hibernate integrating with each format's "serializer" is
> the proper solution.
>
>
>
> On Thu, May 4, 2017 at 5:08 AM Christian Beikov <
> christian.beikov at gmail.com> wrote:
>
>> This is exactly what I am trying to do with Blaze-Persistence Entity
>> Views, making DTOs sexy and efficient :)
>>
>> Here a quick overview of how that looks like right now:
>>
>> https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#first-entity-view-query
>>
>> One of my targets is to make it possible to do something like this
>>
>> entityManager.createQuery("FROM Order o", OrderDTO.class).getResultList()
>>
>> and get an optimal query, as well as objects with only the necessary
>> contents.
>>
>> Maybe we can collaborate on that somehow?
>>
>>
>> Mit freundlichen Grüßen,
>> ------------------------------------------------------------------------
>> *Christian Beikov*
>> Am 04.05.2017 um 10:20 schrieb Emmanuel Bernard:
>> > Following up a bit on my previous email.
>> >
>> > While a core integration might be best I think, if there are too much
>> > reluctance, we can start with a dedicated hibernate-dto or whatever
>> > module or even separate project that makes life easier for these "pass
>> > through" use cases. This could be in the form of a wrapper API of sort
>> > and hence not affect existing Hibernate ORM APIs.
>> >
>> > Note that the ResultTransformer approach feels like it goes a long way
>> > towards fixing the problem but as demonstrated in Vlad's article
>> >
>> https://vladmihalcea.com/2017/04/03/why-you-should-use-the-hibernate-resulttransformer-to-customize-result-set-mappings/
>> > it still requires quite a bit of code and a special DTO constructor
>> > object. That's what we need to get rid of I think.
>> >
>> > Emmanuel
>> >
>> > On Thu 17-05-04 10:04, Emmanuel Bernard wrote:
>> >> I was very much in the Vlad, Steve, Christian camp until relatively
>> >> recently. One of my main concern being that replacing a proxy by null
>> >> was really sending the wrong message. So I was against having Hibernate
>> >> ORM facilitate such a transformation.
>> >>
>> >> I am changing my mind because I am realizing that a lot of applications
>> >> are less complex that my perceived median. A lot of apps really just
>> >> want data to be fetched out and then passed to jackson (implicitly) and
>> >> pushed out as a REST response in JSON or some other serialization
>> >> protocol.
>> >>
>> >> So while we could try and keep the stance that such a solution should
>> >> remain out of scope of Hibernate ORM core, we should have a very smooth
>> >> integration with something like MapStruct to create such bounded DTO on
>> >> the fly. Ideally with as close to zero code as possible from the user
>> >> point of view.
>> >> I can't really describe how that could look like because I am not
>> >> familiar enough with MapStruct but I think it should have the following
>> >> characteristics:
>> >>
>> >> 1. do an implicit binding between the mapped object graph and a
>> detached
>> >>    object graph with a 1-1 mapping of type and replacing lazy objects
>> and
>> >>    collections with null. That's the smoothest approach and the most
>> >>    common use case but also the one where an inexperienced person could
>> >>    shoot at someone else's foot
>> >> 2. do a binding between the mapped object graph and a detached version
>> of
>> >>    that object graph with a 1-1 mapping of type, but declaratively
>> >>    expressing the boundaries for the detached version. This enforces a
>> >>    clear thinking of the boundaries and will load lazy data in case the
>> >>    object graph loaded is missing a bit. I like the idea on principle
>> but
>> >>    I think it overlaps a lot with the fetch graph.
>> >> 3. offer a full integration between MapStruct and Hibernate ORM by
>> >>    letting people express a full fledge MapStruct transformation
>> between
>> >>    the managed object graph and a different target structure
>> >>
>> >> I favored MapStruct over Dozer because we know the MapStruct lead
>> quite well ;)
>> >>
>> >> Note however that the MapStruct approach requires an explicit object
>> >> copy, it feels a bit sad to have to double memory consumption. But that
>> >> might be a good enough approach and bypassing the managed object
>> >> creation leads to questions around the Persistence Context contract
>> >> where loading an object supposedly means it will be in the PC.
>> >> Maybe a constructor like query syntax allowing to reference a MapStruct
>> >> conversion logic might work?
>> >>
>> >>     select mapStruct('order-and-items', o) from Order o left join
>> fetch o.items
>> >>
>> >> Emmanuel
>> >>
>> >>
>> >> On Wed 17-04-19 14:29, Vlad Mihalcea wrote:
>> >>> Hi,
>> >>>
>> >>> Although I keep on seeing this request from time to time, I still
>> think
>> >>> it's more like a Code Smell.
>> >>> Entities are useful for when you plan to modify them. Otherwise, a DTO
>> >>> projection is much more efficient, and you don't suffer from
>> >>> LazyInitializationException.
>> >>>
>> >>> With the ResultTransformer, you can even build graphs of entities, as
>> >>> explained in this article;
>> >>>
>> >>>
>> https://vladmihalcea.com/2017/04/03/why-you-should-use-the-hibernate-resulttransformer-to-customize-result-set-mappings/
>> >>>
>> >>> Due to how Hibernate Proxies are handled, without Bytecode
>> Enhancement,
>> >>> it's difficult to replace a Proxy with null after the Session is
>> closed. If
>> >>> we implemented this, we'd have to take into consideration both
>> Javassist
>> >>> and ByteBuddy as well as ByteCode Enhancements.
>> >>>
>> >>> all in all, the implementation effort might not justify the benefit,
>> and
>> >>> I'm skeptical of offering a feature that does not encourage data
>> access
>> >>> Best Practices.
>> >>>
>> >>> Vlad
>> >>>
>> >>> On Wed, Apr 19, 2017 at 2:18 PM, Christian Beikov <
>> >>> christian.beikov at gmail.com> wrote:
>> >>>
>> >>>> Hey Romain,
>> >>>>
>> >>>> I don't think it is a good idea to expose entities directly if you
>> >>>> really need a subset of the data.
>> >>>> Reasons for that thinking are that it gets hard to define what needs
>> to
>> >>>> be fetched or is safe to be used for a particular use case. Obviously
>> >>>> serialization is like a follow-up problem.
>> >>>> I see 2 possible solutions to the problem and both boil down to the
>> use
>> >>>> of DTOs.
>> >>>>
>> >>>>   1. Use an object mapper(e.g. Dozer) that maps entity object graphs
>> to
>> >>>>      custom DTO types.
>> >>>>   2. Use specialized DTOs in queries.
>> >>>>
>> >>>>
>> >>>> Implementing 1. does not help you with lazy loading issues and 2.
>> might
>> >>>> require very intrusive changes in queries which is why I implemented
>> >>>> Blaze-Persistence Entity Views
>> >>>> <https://github.com/beikov/blaze-persistence#entity-view-usage>.
>> >>>> This is a library that allows you to define DTOs with mappings to the
>> >>>> entity. In a query you can define that you want results to be
>> >>>> "materialized" as instances of the DTO type.
>> >>>> This reduces the pain induced by properly separating the
>> "presentation
>> >>>> model" from the "persistence model" and at the same time will improve
>> >>>> the performance by utilizing the mapping information.
>> >>>> I don't want to advertise too much, just wanted to say that I had the
>> >>>> same issues over and over which is why I started that project.
>> >>>>
>> >>>> Mit freundlichen Grüßen,
>> >>>>
>> ------------------------------------------------------------------------
>> >>>> *Christian Beikov*
>> >>>> Am 19.04.2017 um 10:51 schrieb Romain Manni-Bucau:
>> >>>>> Hi guys,
>> >>>>>
>> >>>>> Short sumarry: Wonder if hibernate could get a feature to kind of
>> either
>> >>>>> unproxy or freeze the entities once leaving the managed context to
>> avoid
>> >>>>> uncontrolled lazy loading on one side and serialization issues on
>> another
>> >>>>> side.
>> >>>>>
>> >>>>> Use case example: a common example is a REST service exposing
>> directly
>> >>>>> hibernate entities (which is more and more common with microservice
>> >>>>> "movement").
>> >>>>>
>> >>>>> Objective: the goal is to not need any step - or reduce them a lot -
>> >>>>> between the hibernate interaction and a potential serialization to
>> avoid
>> >>>>> issues with lazy loading and unexpected loading. Today it requires
>> some
>> >>>>> custom and hibernate specific logic in the serializer which kind of
>> >>>> breaks
>> >>>>> the transversality of the two concerns (serialization and object
>> >>>>> management/loading).
>> >>>>>
>> >>>>>
>> >>>>> Implementation options I see:
>> >>>>>
>> >>>>> 1. a callback requesting if the lazy relationship should be fetched,
>> >>>>> something like
>> >>>>>
>> >>>>> public interface GraphVisitor {
>> >>>>>       boolean shouldLoad(Object rootEntity, Property property);
>> >>>>> }
>> >>>>>
>> >>>>> 2. An utility to remove any proxy potentially throwing an exception
>> and
>> >>>>> replacing the value by null or an empty collection, something like
>> >>>>>
>> >>>>> MyEntity e = Hibernate.deepUnproxy(entity);
>> >>>>>
>> >>>>> 3. A switch of the proxy implementation, this is close to 2 but
>> wouldn't
>> >>>>> require a call to any utility, just a configuration in the
>> persistence
>> >>>> unit.
>> >>>>> Side note: of course all 3 options can be mixed to create a single
>> >>>> solution
>> >>>>> like having 3 implemented based on 1 for instance.
>> >>>>>
>> >>>>> Configuration proposal: this would be activated through a property
>> in the
>> >>>>> persistence unit (this shouldn't be only global IMHO cause
>> otherwise you
>> >>>>> can't mix 2 kind of units, like one for JSF and one for JAX-RS to be
>> >>>>> concrete). This should also be activable as a query hint i think -
>> but
>> >>>> more
>> >>>>> a nice to have.
>> >>>>>
>> >>>>>
>> >>>>> What this feature wouldn't be responsible for: cycles. If
>> relationships
>> >>>> are
>> >>>>> bidirectional then the unproxied entity would still "loop" if you
>> browse
>> >>>>> the object graph - this responsability would stay in the consumer
>> since
>> >>>> it
>> >>>>> doesn't depend on hibernate directly but more on a plain object
>> handling.
>> >>>>>
>> >>>>> What do you think?
>> >>>>>
>> >>>>>
>> >>>>> Romain Manni-Bucau
>> >>>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
>> >>>>> <https://blog-rmannibucau.rhcloud.com> | Old Blog
>> >>>>> <http://rmannibucau.wordpress.com> | Github <https://github.com/
>> >>>> rmannibucau> |
>> >>>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | JavaEE Factory
>> >>>>> <https://javaeefactory-rmannibucau.rhcloud.com>
>> >>>>> _______________________________________________
>> >>>>> 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
>> >> _______________________________________________
>> >> 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