Quantcast
Channel: Learning the code way
Viewing all articles
Browse latest Browse all 231

Criteria and Inner joins

$
0
0
Few posts ago we saw HQL's extensive support for joins. I decided to check out Criteria's claims to the same. I decided to start out with Inner joins.
Just to recollect:
The SQL INNER JOIN clause tells the database to only return rows where there is a match found between table1 and table2. An INNER JOIN is most often (but not always) created between the primary key column of one table and the foreign key column of another table.
We saw how querying on associations or selecting data inside associations may result in implicit join queries. I tried the same for Criteria.
publicstatic void testJoinViaAssociationInWhere() {
final Session session = sessionFactory.openSession();
Criteria criteria = session.createCriteria(Entity.class);
criteria.createAlias("master", "master");
criteria.add(Restrictions.like("master.data", "master No 1"));
System.out.println(criteria.list());
}
Here a restriction was applied on association data( other than an id). The result was :
Hibernate: 
/* criteria query */
select
this_.ID as ID0_1_,
this_.NAME as NAME0_1_,
this_.DATE as DATE0_1_,
this_.MASTER_ID as MASTER4_0_1_,
master1_.ID as ID1_0_,
master1_.DATA as DATA1_0_
from
ENTITY this_
inner join
ENTITY_MASTER master1_
on this_.MASTER_ID=master1_.ID
where
master1_.DATA like ?

[[Entity] : ( id 2 , data : entity1 , master.Id : 1 , date : null )], [Entity] :
( id 3 , data : entity2 , master.Id : 1 , date : null )]]
Criteria resulted in an explicit inner join. Similarly when we try loading association data in a projection :
publicstatic void testJoinViaAssociationInSelect() {
final Session session = sessionFactory.openSession();
Criteria criteria = session.createCriteria(Entity.class);
criteria.createAlias("master", "master");
criteria.add(Restrictions.eq("id", 3));
criteria.setProjection(
Projections.projectionList()
.add(Property.forName("master.data")));
System.out.println(criteria.list());
}
The generated SQL is :
Hibernate: 
/* criteria query */
select
master1_.DATA as y0_
from
ENTITY this_
inner join
ENTITY_MASTER master1_
on this_.MASTER_ID=master1_.ID
where
this_.ID=?

[master No 1]
The SQL generated in both cases was an explicit join unlike HQL which used implicit joins for the two cases.
In both the examples the createAlias() method is very important.If the joined entity is not aliased then the code throws exception:
Exception in thread "main" org.hibernate.QueryException: could not resolve prope
rty: master.data of: com.model.Entity
at org.hibernate.persister.entity.AbstractPropertyMapping.propertyException(Abs
tractPropertyMapping.java:44
)
at org.hibernate.persister.entity.AbstractPropertyMapping.toColumns(AbstractPro
pertyMapping.java:59
)
at org.hibernate.persister.entity.BasicEntityPropertyMapping.toColumns(BasicEnt
ityPropertyMapping.java:31
)
at org.hibernate.persister.entity.AbstractEntityPersister.toColumns(AbstractEnt
ityPersister.java:1350
)

The other technique for applying inner joins is to use nested criteria objects.Consider the below method:
publicstatic void testJoinViaAssociationInWhereUsingNestedCriteria() {
final Session session = sessionFactory.openSession();
Criteria criteria = session.createCriteria(Entity.class);
Criteria nestedCriteria = criteria.createCriteria("master");
nestedCriteria.add(Restrictions.like("data", "master No 1"));
System.out.println(criteria.list());
}
The method is for the same query as testJoinViaAssociationInWhere() method. The generated query is also equivalent. However the technique used here is not alias but to create another criteria instance. The creation of the second criteria for the "master" association results in an inner join between the two tables.
The createCriteria() method will return a Subcriteria instance (A final inner class).
I tried the same technique for projection based inner joins:
publicstatic void testJoinViaAssociationInSelectUsingNestedCriteria() {
final Session session = sessionFactory.openSession();
Criteria criteria = session.createCriteria(Entity.class);
criteria.add(Restrictions.eq("id", 3));

Criteria nestedCriteria = criteria.createCriteria("master");
nestedCriteria.setProjection(Projections.projectionList().add(
Property.forName("data")));
System.out.println(nestedCriteria.list());
}
This however did not work and resulted in the below exception:
Exception in thread "main" org.hibernate.QueryException: could not resolve prope
rty: data of: com.model.Entity
at org.hibernate.persister.entity.AbstractPropertyMapping.propertyException(Abs
tractPropertyMapping.java:44
)
at org.hibernate.persister.entity.AbstractPropertyMapping.toType(AbstractProper
tyMapping.java:38
)


Viewing all articles
Browse latest Browse all 231

Trending Articles