1

Let's assume, each song belongs to exactly one album created by exactly one artist living in exactly one country. A query like

createCriteria(Song.class)
    .add(Restrictions.eq("album.artist.country.id", 43)); 

fails and can be fixed using createAlias or createCriteria (like here) so that the needed joins get performed. I'm doing it and it works, but I'm missing some background:

Why does it work like this? Assuming no embedded properties, joining is the only choice, isn't it?

Concerning the join type, there's no ambiguity: It must be an INNER JOIN, otherwise the equality could not hold, right?

Community
  • 1
  • 1
maaartinus
  • 44,714
  • 32
  • 161
  • 320
  • 1
    I cannot tell you why it is required to create subcriteria but you can use a flexible approach which generates those criteria tree automatically like: http://stackoverflow.com/questions/12003143/generic-dao-and-nested-properties-support/12043844#12043844 I use this for 90% of my queries, especially generic filternig queries by CRUD GUI applications. – djmj Mar 27 '16 at 22:32

2 Answers2

1

The questions about why something is built the way it is are always tricky, and you would probably need to ask authors directly about it.

I was not able to find any official documentation about this, but I assume it has to do with String-based queries (HQL) vs object-based queries (Criteria).

The query you wrote is anyway more HQL than Criteria, so why not use HQL for the entire query?

I understand that this is just a short example you wrote to describe the concept and that it may be convenient to use String-based path navigation joins in more complex Criteria queries also, but the point of Criteria is to provide more type-safe queries and reusable criteria parts which you can use to build the query in chunks, based on various other conditions that that influence what the final query will look like.

For example, say you have predefined constants for all of the entity properties so that you are sure you don't make any typos when working with String-based queries:

public final class Album_ {
  public static final String artist = "artist";
}

public final class Artist_ {
  public static final String country = "country";
}

There are tools/frameworks that generate these classes automatically.

So, you can generate a Criteria the following way:

createCriteria(Song.class)
 .createCriteria(Album_.artist)
 .createCriteria(Artist_.country)
 ...

For most queries the above approach is an unnecessary overhead and make the code less readable IMHO (I personally find HQL/JPQL more readable even when StringBuilder or similar is involved), but I think that's the basic idea behind Criteria: safer and more reusable query parts.

Dragan Bozanovic
  • 23,102
  • 5
  • 43
  • 110
  • To react to your questions: *why not use HQL for the entire query* - I find pre-JPA criteria to be the right middle ground between readability and safety. It gives me a good feeling I'm missing with HQL. YMMV. +++ Type-safe JPA criteria is unreadable for me, too, and I have no use for all the needed intermediate criteria. +++ FYI I wrote a very tiny wrapper allowing to write `createCriteria(Song.class).addEq("album.artist.country.id", 43)` which covers 90% of all my restrictions and makes my queries half as verbose as before. – maaartinus Apr 23 '16 at 03:19
  • 1
    @maaartinus You may want to take a look at [`Querydsl`](http://www.querydsl.com/static/querydsl/latest/reference/html/ch02.html). I have found it to be a perfect balance between JPQL's '`String`-ness' and Criteria's verbosity. – Dragan Bozanovic May 14 '16 at 11:35
  • Currently, I'm rather happy with Criteria, but when some big changes come, I'll surely look into Querydsl. I'm not much concerned about type safety now (I had no corresponding problems recently), but a tool providing both nicer *and* more type-safe solution sounds really good! – maaartinus May 14 '16 at 15:15
0

Concerning the join type, there's no ambiguity: It must be an INNER JOIN, otherwise the equality could not hold, right?

You should use INNER JOIN.

Why does it work like this?

Because hibernate generates, so you should put alias.

Have you thought about Hibernate Native SQL instead? Because there would be a messy query to database.

Hamedz
  • 726
  • 15
  • 27