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.bei...@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@lists.jboss.org >>> > https://lists.jboss.org/mailman/listinfo/hibernate-dev >>> >>> _______________________________________________ >>> hibernate-dev mailing list >>> hibernate-dev@lists.jboss.org >>> https://lists.jboss.org/mailman/listinfo/hibernate-dev >>> >>_______________________________________________ >>hibernate-dev mailing list >>hibernate-dev@lists.jboss.org >>https://lists.jboss.org/mailman/listinfo/hibernate-dev >_______________________________________________ >hibernate-dev mailing list >hibernate-dev@lists.jboss.org >https://lists.jboss.org/mailman/listinfo/hibernate-dev _______________________________________________ hibernate-dev mailing list hibernate-dev@lists.jboss.org https://lists.jboss.org/mailman/listinfo/hibernate-dev