I've done some very basic benchmarking. And I'm not pretending I'm a benchmark specialist. Many other factors may be playing here.
I've inserted 10000 games records the following way
for(int i=0;i<10000;i++)
{
String p1 = "name" + (i+1);
String p2 = "name" + (i+2);
hibSession.save(new Game(new Participation(new Person(p1)),new Participation(new Person(p2))));
}
Then on my mysql database I performed the following queries:
Query1: How I would write my own sql
mysql> select game0_.id as id,
-> game0_.participation1 as particip2_,
-> game0_.participation2 as particip3_
-> from Game game0_,
-> Participation participat1_
-> where (participat1_.person IN(1) and game0_.participation1=participat1_.id)
-> OR(participat1_.person IN(1) and game0_.participation2=participat1_.id);
+----+------------+------------+
| id | particip2_ | particip3_ |
+----+------------+------------+
| 1 | 1 | 2 |
+----+------------+------------+
1 row in set (0.02 sec)
Query2:generated by hibernate
SELECT game from Game game
inner join game.participation1 p1
inner join game.participation2 p2
where p1.person.id in (1) or p2.person.id in (1)
resulted in the folowing query generated by hibernate:
mysql> select game0_.id as id,
-> game0_.participation1 as particip2_,
-> game0_.participation2 as particip3_
-> from Game game0_
-> inner join Participation participat1_ on game0_.participation1=participat1_.id
-> inner join Participation participat2_ on game0_.participation2=participat2_.id
-> where (participat1_.person in(1))or(participat2_.person in(1));
+----+------------+------------+
| id | particip2_ | particip3_ |
+----+------------+------------+
| 1 | 1 | 2 |
+----+------------+------------+
1 row in set (0.11 sec)
As you cas see from the timings made by mysql: My handwrited sql is 5 times faster. I may be wrong and have forgotten about other factors. But I've tested every query 10 times switching between them. And the result remained.
Quote:
This is honestly all very correct since Hibernate has inner join semantics for path expressions (if we would have chosen outer join semantics, it would handle this situation better, but I think usually inner join is more convenient).
==>Inner, right or left join. It is one join to much. Hibernate should be able to see that game.participation1 and game.participation2 apply on the same table. And therefore conclude that one join is enough.
I can see the following answers to my question:
a)In a perfect world, hibernate would see that the participations aply on the same table and therefore hibernate can conclude that one join is sufficient. But for now, this isn't the case.
b)It is better that hibernate uses 2 joins because in other situations 1 join causes problems.(maybe hibernate can't be certain that the participations apply on the same table. Because participation might be a superclass)
A simple a or b will stop me from asking more questions because I'm not intending to waste your time with allready resolved issues. I'm not well enough informed to understand the complete picture.
Greetz