Search This Blog

Thursday, 25 October 2012

Theta Style Joins

Consider the below queries to find all children of an entity:
public static void testGetEntityChild() {
    final Session session = sessionFactory.openSession();
    Query q = session.createQuery("Select c from Entity e, Child c where e = c.parent");
    List<Child> children = q.list(); 
    System.out.println(children);
    q = session.createQuery("Select c from Entity e join e.children c ");
    children = q.list(); 
    System.out.println(children);
    session.close();
}
The output of the above is as below:
Hibernate: 
    /* Select
        c 
    from
        Entity e,
        Child c 
    where
        e = c.parent */ 
        select
            child1_.ID as ID2_,
            child1_.`KEY` as KEY2_2_,
            child1_.ENTITY_ID as ENTITY3_2_ 
        from
            ENTITY entity0_,
            CHILD_ENTITY child1_ 
        where
            entity0_.ID=child1_.ENTITY_ID
[[Child] : ( id 1 , key : 1001 , parent.Id : 1 )], [Child] : ( id 2 , key : 1001
 , parent.Id : 1 )]]
Hibernate: 
    /* Select
        c 
    from
        Entity e 
    join
        e.children c  */ 
        select
            children1_.ID as ID2_,
            children1_.`KEY` as KEY2_2_,
            children1_.ENTITY_ID as ENTITY3_2_ 
        from
            ENTITY entity0_ 
        inner join
            CHILD_ENTITY children1_ 
                on entity0_.ID=children1_.ENTITY_ID
[[Child] : ( id 1 , key : 1001 , parent.Id : 1 )], [Child] : ( id 2 , key : 1001
 , parent.Id : 1 )]]
AS we can see both the HQL statements generate different queries. The second query is an explicit inner join between entity and children. What about the first then. It is no implicit join.It is actually a cartesian product of all records in entities and children on which a where clause was applied restricting the final set.
The following would therefore result in just a Cartesian Product.
final Session session = sessionFactory.openSession();
    Query q = session.createQuery("Select c from Entity e, Child c");
    List<Child> children = q.list(); 
    System.out.println(children);
Output:
Hibernate: 
    /* Select
        c 
    from
        Entity e,
        Child c */ 
        select
            child1_.ID as ID2_,
            child1_.`KEY` as KEY2_2_,
            child1_.ENTITY_ID as ENTITY3_2_ 
        from
            ENTITY entity0_,
            CHILD_ENTITY child1_
[[Child] : ( id 1 , key : 1001 , parent.Id : 1 )], [Child] : ( id 1 , key : 1001
 , parent.Id : 1 )], [Child] : ( id 2 , key : 1001 , parent.Id : 1 )], [Child] :
 ( id 2 , key : 1001 , parent.Id : 1 )]]
As can be seen all combinations of child and entity were returned.
This kind of a cartesian product join is rarely of any use. However the ability to join two unrelated tables is needed. Consider the case where we need all Master and Child pairs that have the same identifier value.
public static void testThetaStyleJoin() {
    final Session session = sessionFactory.openSession();
    Query q = session.createQuery("from Master m, Child c where m.id = c.id");
    List<Object[]> objects = q.list(); 
    for (Object[] object : objects) {
        System.out.println(object[0] + " and " + object[1]);
    }
    session.close();
}
The output is as below:
Hibernate: 
    /* 
from
    Master m,
    Child c 
where
    m.id = c.id */ 
    select
        master0_.ID as ID1_0_,
        child1_.ID as ID2_1_,
        master0_.DATA as DATA1_0_,
        child1_.`KEY` as KEY2_2_1_,
        child1_.ENTITY_ID as ENTITY3_2_1_ 
    from
        ENTITY_MASTER master0_,
        CHILD_ENTITY child1_ 
    where
        master0_.ID=child1_.ID
[Master] : ( id 1 , data : master No 1 )] and [Child] : ( id 1 , key : 1001 , pa
rent.Id : 1 )]
Such joins are called theta style joins - a cartesian product + a where condition to restrict the result.

No comments:

Post a Comment