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 <st...@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.bei...@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.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 >> >> _______________________________________________ >> 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