1

we have an entity that has a lot of ManyToOne, OneToOne, etc relations which themself have again some relations. For example

@OneToMany(targetEntity = Season.class, cascade = {
    CascadeType.ALL
})
@JoinColumn(name = "SEASON_ID")
  public List<Season> getSeasons(){...}

(I can not change this).

Those are loaded lazily (by default I think) which is good and we don’t want to change this. Now we have this one case, where we want to find the whole entity eagerly by it's id to return it.

I found a lot of suggestions to change the entity and discussions about wether eager or lazy loading is better, which do not help me at this point, since the entity is out of reach for us. Is there a way to do this, without changing the entity and without having to call every possible getter to initialize the lazy entities (because those are too many)? So for example, the answer to Question 24573877 does not work for me.

Basically I want to say "load the entity eagerly, but just this once". Currently I'm just doing return em.find(MyEntity.class, contractId) (I could change this).

Thanks and regards Urr4

Community
  • 1
  • 1
Urr4
  • 611
  • 9
  • 26

2 Answers2

2

look at : http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html

chapter : 14.3. Associations and joins

A "fetch" join allows associations or collections of values to be initialized along with their parent objects using a single select. This is particularly useful in the case of a collection. It effectively overrides the outer join and lazy declarations of the mapping file for associations and collections. See Section 19.1, “Fetching strategies” for more information.

You've to write your query instead of use em.find.

exemple this query :

from Cat as cat inner join fetch cat.mate left join fetch cat.kittens

will return cat with mate and kittens already loaded (eager), even if they have been initialized in lazy

Edit : Or you can use fetch profil :

In order to mitigate these, Hibernate propose a fetch strategy that works not on the mapping level, but on the request level. Thus, you can still have lazy loading mappings but eager fetching in some cases.

look at : https://blog.frankel.ch/hibernate-hard-facts-part-6

Zakaria
  • 108
  • 1
  • 9
  • Thank you for your answer, but what if in your example the kittens have for example "brothers" that are also kittens. Do I have to do more fetch join in the query to eagerly load those too? In my situation, the datamodel is very complex and very huge and I hope to avoid adding every sub-entity to the query. – Urr4 Oct 24 '15 at 16:13
  • you must add as many fetch as there's relation in lazy , I think you can do it even if it is complex if it is for 1 or 2 queries . If you realize that you often need to retrievie entites relation, you'll have to rethink your load configuration for this entity. good luck! – Zakaria Oct 25 '15 at 23:21
  • Ok, that is very good to know, but sadly this only helps me a little. Like i said, the entity is huge with lots of relationships and many of those are unknown to me. It may be easier, writing a statement instead of calling every getter but I still need to know every aspect of the entity to build the statement. I hoped there would be a way to avoid this. Lazy initialisation is the best choise in our domain, just not in this one case, so I don't want to change this. – Urr4 Oct 27 '15 at 10:27
  • I see, you can use fetchprofile, to let lazy loading mappings but eager fetching in some cases. look at https://blog.frankel.ch/hibernate-hard-facts-part-6 – Zakaria Oct 27 '15 at 10:51
  • Thanks, this looks like the right way to go :)- There's still the problem that most associations inside the entity are unknown to me and many of those have associations themself. I don't want to add tons of fetch profiles to get a deep copy of the entity. It feels like there should be an easier way. In terms of fetch profiles,I'm looking for something like `@FetchProfile(fetchOverrides = { @FetchOverride(association =ALL, entity = MyEntity.class, mode = FetchMode.JOIN) }, name = “LOAD-DEEP-CLONE-EAGERY”)` – Urr4 Nov 09 '15 at 09:49
0

I didn't really solve it the way i wanted to, but it works now. It seems, there really is no way to eagerly load an entity, you know nothing about. Our problem was, that the entity came from a 3rd-party Maven dependency and was unchangeable and hard to look into. In the end we build an entityProcessor, that took the lazily loaded entity and called every getter and all the getters of the child entities recursively. If we have control over an entity, i will use FetchProfiles next time, otherwise, I'd recommend implementing a clone() function.

Urr4
  • 611
  • 9
  • 26