Consider a query to fetch all entities who have a child with id 1.
Or is it ?
The size of the set is indicated as 1. This is not the case. If I remove the where condition then the console logs would be :
The second query while revealing the correct size of children faced another problem. The Entity object appears twice in the list. This is repeat data and unnecessary.
We need the entity to be returned once only. For this we use the DISTINCT keyword.
The changed code is
I executed the above query direct on the MySQL workbench. The result is :
As can be seen the result set has the same Entity details occurring twice, in fact you would get the same result if you removed the distinct command from the SQL.
The distinct keyword does not affect the SQL query in any manner. It is actually used by hibernate. The presence of distinct keyword ensures that Hibernates does the filtering in memory and removes all duplicates. So our result has only one entity record now.
public static void testQuerySingleE() { final Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction(); System.out.println("Testing the loading"); Query q = session.createQuery("select e from Entity e" + " join fetch e.children c where c.id = 1"); @SuppressWarnings("unchecked") List<Entity> entities = q.list(); for (Entity entity : entities ) { System.out.println("entity is " + entity + " and no of kids are " + entity.getChildren().size()); } transaction.commit(); session.close(); }The output is as below:
/* select e from Entity e join fetch e.children c where c.id = 1 */ select entity0_.ID as ID0_0_, children1_.ID as ID2_1_, entity0_.NAME as NAME0_0_, entity0_.DATE as DATE0_0_, entity0_.MASTER_ID as MASTER4_0_0_, children1_.`KEY` as KEY2_2_1_, children1_.ENTITY_ID as ENTITY3_2_1_, children1_.ENTITY_ID as ENTITY3_0__, children1_.ID as ID0__ from ENTITY entity0_ inner join CHILD_ENTITY children1_ on entity0_.ID=children1_.ENTITY_ID where children1_.ID=1 entity is [Entity] : ( id 1 , data : entity1 , master.Id : 1 , date : null )] an d no of kids are 1The join query returned a set of 2 entity-child record and the where clause trimmed it to 1. Everything is fine.
Or is it ?
The size of the set is indicated as 1. This is not the case. If I remove the where condition then the console logs would be :
Testing the loading Hibernate: /* select e from Entity e join fetch e.children c */ select entity0_.ID as ID0_0_, children1_.ID as ID2_1_, entity0_.NAME as NAME0_0_, entity0_.DATE as DATE0_0_, entity0_.MASTER_ID as MASTER4_0_0_, children1_.`KEY` as KEY2_2_1_, children1_.ENTITY_ID as ENTITY3_2_1_, children1_.ENTITY_ID as ENTITY3_0__, children1_.ID as ID0__ from ENTITY entity0_ inner join CHILD_ENTITY children1_ on entity0_.ID=children1_.ENTITY_ID entity is [Entity] : ( id 1 , data : entity1 , master.Id : 1 , date : null )] an d no of kids are 2 entity is [Entity] : ( id 1 , data : entity1 , master.Id : 1 , date : null )] an d no of kids are 2The problem is that we have used the fetch attribute.
- This means an eager load for association.
- This results in Hibernate using the association columns to fill up the set. So the data from the two Records was used to create the two children for Entity1.
- But with the where clause we applied the condition on our children table, this reduced the size of the result set and hence the children set has fewer than correct elements.
The second query while revealing the correct size of children faced another problem. The Entity object appears twice in the list. This is repeat data and unnecessary.
We need the entity to be returned once only. For this we use the DISTINCT keyword.
The changed code is
public static void testQuerySingleE() { final Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); System.out.println("Testing the loading"); Query q = session.createQuery("select distinct(e) from " + "Entity e join fetch e.children c"); // where c.id = 1"); List<Entity> entities = q.list(); for (Entity entity : entities ) { System.out.println("entity is " + entity + " and no of kids are " + entity.getChildren().size()); } transaction.commit(); session.close(); }and the logs are :
Testing the loading
Hibernate:
/* select
distinct(e)
from
Entity e
join
fetch e.children c */
select
distinct entity0_.ID as ID0_0_,
children1_.ID as ID2_1_,
entity0_.NAME as NAME0_0_,
entity0_.DATE as DATE0_0_,
entity0_.MASTER_ID as MASTER4_0_0_,
children1_.`KEY` as KEY2_2_1_,
children1_.ENTITY_ID as ENTITY3_2_1_,
children1_.ENTITY_ID as ENTITY3_0__,
children1_.ID as ID0__
from
ENTITY entity0_
inner join
CHILD_ENTITY children1_
on entity0_.ID=children1_.ENTITY_ID
entity is [Entity] : ( id 1 , data : entity1 , master.Id : 1 , date : null )] an
d no of kids are 2
The distinct keyword is visible in the SQL logs.I executed the above query direct on the MySQL workbench. The result is :
As can be seen the result set has the same Entity details occurring twice, in fact you would get the same result if you removed the distinct command from the SQL.
The distinct keyword does not affect the SQL query in any manner. It is actually used by hibernate. The presence of distinct keyword ensures that Hibernates does the filtering in memory and removes all duplicates. So our result has only one entity record now.
No comments:
Post a Comment