Search code examples
javahibernatejoinhibernate-criteriacriteria-api

How to restrict Hibernate to generate SQL query with columns only from root entity in Criteria API involving multiple entities


I have written hibernate code with criteria API involving multiple entities (having parent-child relationships & I am using createAlias() to join entities) expecting to fetch only root entity in the result.

However, when I debug the SQL generated by hibernate I observe that hibernate is fetching data (in select clause) for all the entities used in the join clause (achieved with createAlias()).

I don't think there is any need to fetch the columns for other entity other than the expected root entity since it may not be efficient and I am looking to avoid this?

I am using Hibernate version 3.6.9

Here is the scenario. There are 3 entities A, B & C having parent child relationship in following manner A (super parent) -> B (parent) -> C (child)

session.createCriteria(B.class, "b")
.createAlias("b.c", "c",Criteria.INNER_JOIN)
.createAlias("b.a", "a",Criteria.INNER_JOIN)
.add(Restrictions.in("c.prop1c", <<some value>>))
.add(Restrictions.in("a.prop1a", <<some value>>))
criteria.list()

now when hibernate generates the SQL it looks like
select 
b.all columns of B
a.all columns of A
c.all columns of C
from B b
inner join A a on b.prop=a.prop
inner join C C on b.prop=c.prop
where
c.prop1c = <<some value>>
a.prop1a = <<some value>>

if you observe hibernate has generate query to fetch all columns of all entities (A, B & C) however as of now i don't need any entity other than root entity (B), data for entities like A & C should be fetched later on as per fetch strategies on their mappings to B. I think there is no need to fetch all the data over the n/w traffic for this query, still hibernate is generating the query like this.

Is there a way I can guide hibernate to only fetch columns for entity B and not for A & C using criteria API?

select 
b.all columns of B
from B b
inner join A a on b.prop=a.prop
inner join C C on b.prop=c.prop
where
c.prop1c = <<some value>>
a.prop1a = <<some value>>

Solution

  • The legacy Criteria is deprecated. You can use the JPA Criteria which supports this via the JOIN directive as opposed to FETCH.

    Or, use JPQL:

    select b
    from B b
    inner join b.a. a
    inner join b.a. c
    where
    c.prop1c = :prop1c 
    a.prop1a = :prop1a