2017-05-04 19:28 GMT+02:00 Steve Ebersole <st...@hibernate.org>: > I should clarify... if your `serialzer#serialize` call is not > "recursively" calling into this check then my example would not work; but > then again, neither would yours >
Well mine works (no "would" ;)) cause jsonb implements the visitor pattern for me in my case. But ok, let's see this Navigable solution when out, sounds promishing. > > On Thu, May 4, 2017, 12:26 PM Steve Ebersole <st...@hibernate.org> wrote: > >> Hibernate#isInitialized is an overloaded method. I think you want to >> look at the different forms. >> >> And yes, Navigable will define visitor-based navigation. Hence the name ;) >> >> On Thu, May 4, 2017, 12:18 PM Romain Manni-Bucau <rmannibu...@gmail.com> >> wrote: >> >>> 2017-05-04 19:16 GMT+02:00 Steve Ebersole <st...@hibernate.org>: >>> >>>> But your psuedo code is really just the same as: >>>> >>>> AnEntity e = find(); >>>> if ( isInitialized( e ) ) { >>>> serializer.serialize(e); >>>> } >>>> >>> >>> no cause it is done in the graph visitor and not just the root, that's >>> the key difference. >>> >>> >>>> >>>> boolean isInitialized(Object e) { >>>> return Hibernate.isInitialized( e ); >>>> } >>>> >>>> What I was getting at with the 6.0 + Navigavble discussion is that it >>>> would be better to base this "isInitialized" on these Navigables instead. >>>> A Navigable is a polymorphic reference that might be an entity, a >>>> persistent attribute, a "collection element", etc. >>>> >>> >>> Would need to see it in a more concrete version but sounds tempting, >>> would it integrate a visitor - handling cycles? >>> >>> >>>> >>>> >>>> On Thu, May 4, 2017 at 11:46 AM Romain Manni-Bucau < >>>> rmannibu...@gmail.com> wrote: >>>> >>>>> 2017-05-04 18:42 GMT+02:00 Christian Beikov < >>>>> christian.bei...@gmail.com>: >>>>> >>>>>> Detecting if an object is initialized should be as easy as calling " >>>>>> Hibernate.isInitialized(object)". If you want to know whether a >>>>>> specic attribute of an object is initialized you'd use >>>>>> "Hibernate.isPropertyInitialized(object, >>>>>> attributeName)". What you want is some kind of integration that >>>>>> makes use of these two methods, so that if they return false, a null >>>>>> value >>>>>> is used when serializing objects to XML/JSON via JAXB/JSONB. Is that >>>>>> correct? >>>>>> >>>>> >>>>> Almost, I would like one able to just disable it, this way the >>>>> serializer doesnt need anything or knowledge of hibernate. Worse case we >>>>> need to integrate with the serializer in a way close to the one i proposed >>>>> for johnzon before. >>>>> >>>>> In pseudo code it would be: >>>>> >>>>> AnEntity e = find(); >>>>> Hibernate.disableLazyExceptionWithNull(e); >>>>> serializer.serialize(e); >>>>> >>>>> >>>>>> I don't know of any hook in JAXB that could be used to put that code >>>>>> into so it works out as you'd expect it. The only other way I can think >>>>>> of, >>>>>> is nulling the properties explicitly which could be done quite easily. >>>>>> You >>>>>> probably gonna need just a single recursive method to do that. I don't >>>>>> see >>>>>> how that method should be part of Hibernate nor how you'd expect to be >>>>>> able >>>>>> to configure Hibernate so that it would do that transparently. >>>>>> >>>>> the switch of lazyexception to null would work wit jaxb. Otherwise you >>>>> need some more low level integration not portable IIRC. >>>>> >>>>> >>>>>> I still think the cleanest solution would be to have DTOs, which is >>>>>> why I'd argue that such a halve solution shouldn't be part of Hibernate. >>>>>> >>>>> >>>>> Think we all agree (or agreed already ;)) but created this thread >>>>> cause i saw it often enough to be a need. >>>>> >>>>> >>>>>> >>>>>> Mit freundlichen Grüßen, >>>>>> ------------------------------ >>>>>> *Christian Beikov* >>>>>> Am 04.05.2017 um 18:00 schrieb Romain Manni-Bucau: >>>>>> >>>>>> >>>>>> >>>>>> 2017-05-04 17:33 GMT+02:00 Steve Ebersole <st...@hibernate.org>: >>>>>> >>>>>>> What exactly would this "utility one level further than existing >>>>>>> ones" do? >>>>>>> >>>>>>> >>>>>> Multiple options are possible but one is to return null instead of >>>>>> throwing lazy exception for instance. >>>>>> >>>>>> >>>>>>> And for what it is worth, IMO the new Navigable model in 6.0 will >>>>>>> again >>>>>>> help here. Especially in conjunction with the Navigable visitation >>>>>>> support. >>>>>>> >>>>>> >>>>>> I'm not familiar enough but if it providers for each member a way to >>>>>> know if it is loaded or not it can work. >>>>>> >>>>>> >>>>>>> >>>>>>> On Thu, May 4, 2017 at 10:27 AM Christian Beikov < >>>>>>> christian.bei...@gmail.com> >>>>>>> wrote: >>>>>>> >>>>>>> > Well that is again exactly what a DTO is good for. If you as >>>>>>> developer >>>>>>> > want the groups to be available, you add a list of groups to that >>>>>>> > special DTO type for that use case. In your data access layer you >>>>>>> > somehow populate that, which is normally done by using some mapper >>>>>>> > library like MapStruct or Dozer and then JAXB/JSONB can just work >>>>>>> with >>>>>>> > the DTO type without any problems. >>>>>>> > >>>>>>> > Now if you forget to add a JOIN FETCH to your query and you end up >>>>>>> with >>>>>>> > N+1 queries, that's a different problem, just like the amount of >>>>>>> > boilerplate code needed for having DTO types for every use case. >>>>>>> That I >>>>>>> > try to solve with Blaze-Persistence Entity Views. >>>>>>> > >>>>>>> > Just a quick example to make my point here. If you have a REST >>>>>>> endpoint >>>>>>> > /user/{id} and want to provide the list of group names along with >>>>>>> the >>>>>>> > user information, you'd create a UserInfoDTO. >>>>>>> > >>>>>>> > @EntityView(User.class) >>>>>>> > interface UserInfoDTO { >>>>>>> > String getUsername(); >>>>>>> > @Mapping("groups.name") >>>>>>> > List<String> getGroups(); >>>>>>> > } >>>>>>> > >>>>>>> > Your repository returns an object of that type and you just pass >>>>>>> that >>>>>>> > object through so JAXB/JSONB can do their work. The mapping >>>>>>> information >>>>>>> > in the DTO is applied on a "source query" i.e. only doing the work >>>>>>> > absolutely necessary to satisfy the requested projection. >>>>>>> > >>>>>>> > Implementing this by hand is by no means impossible, but rather >>>>>>> > inconvenient I'd say, which is probably why you are seeking for >>>>>>> other >>>>>>> > solutions. >>>>>>> > >>>>>>> > In the end, you can only try to create a minimal DTO that has >>>>>>> exactly >>>>>>> > the fields you want to be serialized or annotate your existing >>>>>>> entities >>>>>>> > with those "ignore" annotations and hope for the best. I don't see >>>>>>> how >>>>>>> > hibernate could or should help in any of the two cases. >>>>>>> > >>>>>>> > Mit freundlichen Grüßen, >>>>>>> > ------------------------------------------------------------ >>>>>>> ------------ >>>>>>> > *Christian Beikov* >>>>>>> > Am 04.05.2017 um 16:59 schrieb Romain Manni-Bucau: >>>>>>> > > Sure. If you add any conversion logic then you are clearly out of >>>>>>> > > hibernate scope and the problem doesnt appear anymore. Here is a >>>>>>> > > trivial example (hopefully trivial at least ;)) >>>>>>> > > >>>>>>> > > User 1 - n Group >>>>>>> > > >>>>>>> > > In json we would get something like {username:...,groups:[group1, >>>>>>> > > group2]}, no issue to know if group should be loaded or not >>>>>>> since this >>>>>>> > > part of the logic is in the mapper layer. >>>>>>> > > >>>>>>> > > So yes you can say "not my problem" but next framework will >>>>>>> > > immediately ask "how do i know" and you likely end like all >>>>>>> > > spring-data-rest recommandation with a specific mapping and not a >>>>>>> > > framework solution which is the target of that thread - at least >>>>>>> what >>>>>>> > > I tried to explain ;). >>>>>>> > > >>>>>>> > > 2017-05-04 16:41 GMT+02:00 Christian Beikov >>>>>>> > > <christian.bei...@gmail.com <mailto:christian.bei...@gmail.com >>>>>>> >>: >>>>>>> > > >>>>>>> > > I don't understand what you mean by "you put that logic in >>>>>>> the >>>>>>> > > conversion", could you elaborate? >>>>>>> > > >>>>>>> > > >>>>>>> > > Mit freundlichen Grüßen, >>>>>>> > > >>>>>>> > ------------------------------------------------------------ >>>>>>> ------------ >>>>>>> > > *Christian Beikov* >>>>>>> > > Am 04.05.2017 um 16:32 schrieb Romain Manni-Bucau: >>>>>>> > >> Few more points: >>>>>>> > >> >>>>>>> > >> 1. Dto dont help at any moment - or you put that logic in >>>>>>> the >>>>>>> > >> conversion and you are back to start >>>>>>> > >> 2. Making jaxb/jsonb easy to integrate is the goal IMO. No >>>>>>> need >>>>>>> > >> to integrate with them but just provide some utility one >>>>>>> level >>>>>>> > >> further than existing ones >>>>>>> > >> >>>>>>> > >> Le 4 mai 2017 16:13, "Steve Ebersole" <st...@hibernate.org >>>>>>> > >> <mailto:st...@hibernate.org>> a écrit : >>>>>>> > >> >>>>>>> > >> 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 <mailto: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 >>>>>>> > >> <mailto: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 >>>>>>> > >> < >>>>>>> > 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/ >>>>>>> > >> < >>>>>>> > 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/ >>>>>>> > >> < >>>>>>> > 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 >>>>>>> > >> <mailto: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 >>>>>>> > >> <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 >>>>>>> > >> <https://twitter.com/rmannibucau>> | Blog >>>>>>> > >> >> >>>>> <https://blog-rmannibucau.rhcloud.com >>>>>>> > >> <https://blog-rmannibucau.rhcloud.com>> | Old Blog >>>>>>> > >> >> >>>>> <http://rmannibucau.wordpress.com >>>>>>> > >> <http://rmannibucau.wordpress.com>> | Github < >>>>>>> > https://github.com/ >>>>>>> > >> >> >>>> rmannibucau> | >>>>>>> > >> >> >>>>> LinkedIn <https://www.linkedin.com/in/ >>>>>>> rmannibucau >>>>>>> > >> <https://www.linkedin.com/in/rmannibucau>> | JavaEE >>>>>>> Factory >>>>>>> > >> >> >>>>> <https://javaeefactory-rmannibucau.rhcloud.com >>>>>>> > >> <https://javaeefactory-rmannibucau.rhcloud.com>> >>>>>>> > >> >> >>>>> ______________________________ >>>>>>> _________________ >>>>>>> > >> >> >>>>> hibernate-dev mailing list >>>>>>> > >> >> >>>>> hibernate-dev@lists.jboss.org >>>>>>> > >> <mailto:hibernate-dev@lists.jboss.org> >>>>>>> > >> >> >>>>> >>>>>>> > >> https://lists.jboss.org/mailman/listinfo/hibernate-dev >>>>>>> > >> <https://lists.jboss.org/mailman/listinfo/hibernate-dev >>>>>>> > >>>>>>> > >> >> >>>> _______________________________________________ >>>>>>> > >> >> >>>> hibernate-dev mailing list >>>>>>> > >> >> >>>> hibernate-dev@lists.jboss.org >>>>>>> > >> <mailto:hibernate-dev@lists.jboss.org> >>>>>>> > >> >> >>>> >>>>>>> > >> https://lists.jboss.org/mailman/listinfo/hibernate-dev >>>>>>> > >> <https://lists.jboss.org/mailman/listinfo/hibernate-dev >>>>>>> > >>>>>>> > >> >> >>>> >>>>>>> > >> >> >>> _______________________________________________ >>>>>>> > >> >> >>> hibernate-dev mailing list >>>>>>> > >> >> >>> hibernate-dev@lists.jboss.org >>>>>>> > >> <mailto:hibernate-dev@lists.jboss.org> >>>>>>> > >> >> >>> https://lists.jboss.org/ >>>>>>> mailman/listinfo/hibernate-dev >>>>>>> > >> <https://lists.jboss.org/mailman/listinfo/hibernate-dev >>>>>>> > >>>>>>> > >> >> >> _______________________________________________ >>>>>>> > >> >> >> hibernate-dev mailing list >>>>>>> > >> >> >> hibernate-dev@lists.jboss.org >>>>>>> > >> <mailto:hibernate-dev@lists.jboss.org> >>>>>>> > >> >> >> https://lists.jboss.org/ >>>>>>> mailman/listinfo/hibernate-dev >>>>>>> > >> <https://lists.jboss.org/mailman/listinfo/hibernate-dev >>>>>>> > >>>>>>> > >> >> > _______________________________________________ >>>>>>> > >> >> > hibernate-dev mailing list >>>>>>> > >> >> > hibernate-dev@lists.jboss.org >>>>>>> > >> <mailto:hibernate-dev@lists.jboss.org> >>>>>>> > >> >> > https://lists.jboss.org/ >>>>>>> mailman/listinfo/hibernate-dev >>>>>>> > >> <https://lists.jboss.org/mailman/listinfo/hibernate-dev >>>>>>> > >>>>>>> > >> >> >>>>>>> > >> >> _______________________________________________ >>>>>>> > >> >> hibernate-dev mailing list >>>>>>> > >> >> hibernate-dev@lists.jboss.org >>>>>>> > >> <mailto:hibernate-dev@lists.jboss.org> >>>>>>> > >> >> https://lists.jboss.org/ >>>>>>> mailman/listinfo/hibernate-dev >>>>>>> > >> <https://lists.jboss.org/mailman/listinfo/hibernate-dev >>>>>>> > >>>>>>> > >> >> >>>>>>> > >> > >>>>>>> > >> _______________________________________________ >>>>>>> > >> hibernate-dev mailing list >>>>>>> > >> hibernate-dev@lists.jboss.org >>>>>>> > >> <mailto:hibernate-dev@lists.jboss.org> >>>>>>> > >> https://lists.jboss.org/mailman/listinfo/hibernate-dev >>>>>>> > >> <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