0

I have a common situation with parent-child relation like:

class Parent {
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    List<ChildOne> childrenOne;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) 
    List<ChildTwo> childrenTwo;

    @OneToMany
    List<LazyChild> lazyChildren;

    @Id
    Long id;
}

Then I have the HQL query like:

select lazyChild from Parent p 
join p.lazyChildren lazyChild
where p.id = ? and lazyChild.mnemonic='AAA'

When I execute it I get LazyChild object and it's what I want. But hibernate also initialize all eagerly defined collections and it's what I don't want. It's not intuitive that hibernate makes a separate call to fetch eager associations. I see it by switching to show SQL query.

How to avoid that unnecessary SQL calls?

Mirian
  • 620
  • 1
  • 7
  • 18

2 Answers2

1

By specifying FetchType.EAGER you've said to Hibernate that every time it loads the parent object, you want it to load up those children objects. If you don't want this to happen, you can't specify an Eager fetch type.

Hibernate isn't smart enough to know that when you are querying the Parent you only want the lazyChild. All it knows is that you've made a request to the Parent object, so it needs to load up the eagerly fetch children.

If you are new to Hibernate, you might find my tutorial here helpful.

Community
  • 1
  • 1
JamesENL
  • 6,400
  • 6
  • 39
  • 64
  • 2
    I'm not new to hibernate but its has a parts that I don't know well. I spent some time in debugging and found method that calls doQueryAndInitializeNonLazyCollections :). Looks like you are right. Hibernate will always initialize eager collections when use Parent in query. But it's not the optimal solution from perspective of SQL. – Mirian Aug 06 '14 at 07:40
0

I'm not sure I understand what you want to do. But if you don't want your collections childrenOne and childrenTwo to be loaded, you should probably declare them with FetchType.LAZY .

It seems to me that you're not querying the right entity, if you just want a list of LazyChild, then your HQL should be something like this :

from LazyChild child
where child.parent.id = ? and child.mnemonic='AAA'

Assuming you have the parent mapped in the LazyChild entity :

@ManyToOne //(fetch=FetchType.LAZY) if you don't need to have the parent loaded
@JoinColumn(name = "parent_id")
private Parent parent;
Matt
  • 3,422
  • 1
  • 23
  • 28