stinger
stinger

Reputation: 4136

Hibernate fetch only single child instance

Seems it is a standard problem, but searching for solution have no success. I have parent class Person with two childen sets:

class Person {

@OneToMany(mappedBy = "person", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
Set<Dog> dogs;

@OneToMany(mappedBy = "person", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
Set<Cat> cats;
}

child class Cat (class Dog looks same):

class Cat {
private String name;

@ManyToOne(targetEntity = Person.class, fetch = FetchType.EAGER)
@JoinColumn(name = "PERSON_ID")
public Person getPerson() {
        return person;
    }
}

What is the problem. When I try to retrieve all Persons, which Cat name equals 'Fritz', Hibernate create joined query on table Cat, which name is 'Fritz'. Everything looks fine, but when I expand retrieved Person (in Idea debugger), it contains only single instance of Cat (with name 'Fritz'), despite Person can have multiple Cats. Simultaneously with expanding, Hibernate make other request to Dog table and retrieve all items linked with this Person, and this field populates correctly. How can I force Hibernate to populate field Cat with all items, not only with joined item?

P.S. I use Spring's HibernateTemplate session.get(), not HQL.

EDIT 1. Generated query (the second part executes only when I expand retrieved Person in debugger):

Hibernate:
    select
        person.PERSON_ID,
        person.PERSON_NAME,        
        cat.CAT_ID,
        cat.NAME,        
    from
        PERSON person
    left outer join
        CAT cat
        on person.PERSON_ID=cat.PERSON_ID
    where
        cat.NAME='FRITZ'                            

Hibernate:
    select
        dog.DOG_ID,
        dog.NAME,
        dog.PERSON_ID
    from
        DOG dog
    where
        dog.DOG_ID=1 

EDIT 2. Seems my issue is a former Hibernate bug . But i'm still need help. My Hibernate version is 4.3.

Upvotes: 1

Views: 873

Answers (2)

stinger
stinger

Reputation: 4136

After day of furious efforts, i've got it. The problem was in LEFT_OUTER_JOIN. Replaced it by INNER_JOIN, and all my nested collections become fully filled. For more detailed explanation, see https://hibernate.atlassian.net/browse/HHH-2049

Upvotes: 1

Serge Ballesta
Serge Ballesta

Reputation: 148965

I am not really confident in using a debugger to see how hibernate actually maps association. It uses special collections that it populates on-demand, because populating a collection causes an extra request and Hibernate tries to give a good mix between simplicity and performance.

So when you ask for *the person owning Pussicat`, Hibernate only does the query on table Person unless you eagerly load child table, an will only do the queries on child tables if you list the cats and dogs of that person in code an not in debugger.

And you know you cannot eagerly load all association. If you did, any simply query could load all the database ...

IMHO when you say Hibernate did not populate cats Set, it is only because in the debugger the set is not initially null nor empty and so the debugger does not ask hibernate to issue the query. But if you asked in the code for the list of cats, you would get it correctly.

Upvotes: 3

Related Questions