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

Romain Manni-Bucau rmannibucau at gmail.com
Thu May 4 04:18:13 EDT 2017


For now I integrated it with johnzon:

@Provider
public class ApiHibernateJsonbProvider<T> extends JsonbJaxrsProvider<T> {
    @Override
    protected Jsonb createJsonb() {
        return JsonbProvider.provider().create()
                .withConfig(new JsonbConfig()
                        .setProperty("johnzon.serialize-value-filter",
(SerializeValueFilter) this::shouldIgnoreField))
                .build();
    }

    private boolean shouldIgnoreField(final String
ignoredPropertyName, final Object value) {
        return (HibernateProxy.class.isInstance(value) &&
HibernateProxy.class.cast(value).getHibernateLazyInitializer().isUninitialized())
||
                PersistentCollection.class.isInstance(value) &&
!PersistentCollection.class.cast(value).wasInitialized();
    }
}


So maybe an utility allowing to just integrate with any serializer (which
already browse the model) would be smoother than a specific integration. I
also think spring (and its trendy boot flavor) does that kind of thing
through spring-data-rest.

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>

2017-05-04 10:04 GMT+02:00 Emmanuel Bernard <emmanuel at hibernate.org>:

> 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
>


More information about the hibernate-dev mailing list