Is there any advantage to find an object using the Hibernate's @NaturalId?
I'm concerned about the fact that Hibernate performs two queries to get an object using @NaturalId. The first query just to get the id and the second query to load the real object.
There is also another benefit of using @NaturalID and is related to the use of query cache (I'm basing this answer in Hibernate 4.3.8) If you configure a natural ID and then you query the entity by NaturalID Restrictions#naturalId or Session#byNaturalId you could be hitting query cache even if the table has been modified.
Hibernate keeps a cache of update timestamps of tables to say if a query cache entry is upToDate.
In plain english, if Hibernate has cached the following
You'll want that if the Team with ID will win a new trophy the query "from Team where trophies=10" will no longer return it. To achieve this, Hibernate keeps records of when tables were last updated and then if the query cache entry is older than this timestamp it doesn't trust in it's results.
I say that it doesn't trust because the result can still be valid but Hibernate wouldn't know because the cache is not per entity, for obvious reasons. So, for example if the Team with ID=3 would be uptaded the entry for 1,2 will be invalidated even if those teams wasn't uptaded. Even more, if the Team 1 would be uptaded but his trophies count would remain the same as before, the query cache entry will be invalidated too although it would still be valid.
If we were querying via NaturalID
we will be enabling to Hibernate to trust in the query cache entries even if they weren't upToDate. This will be like saying: "Yes Hibernate, I know that the table was uptaded but I assure you that the NaturalID of these entities weren't changed so you can trust in the entries that correspond to queries by NaturalID".
Hibernate has to check some a couple of things to see if the query can avoid the upToDate check. This can be seen in Loader#getResultFromQueryCache
The flag isImmutableNaturalKeyLookup is passed to Query#get. Let's see how StandardQueryCache uses it.
If isNaturalKeyLookup is true it doesn't check isUpToDate.
Hibernate: Cache Queries the Natural Id Way is an old but great post about query cache and NaturalID that will help to understand.
At least one advantage is you will benefit from first level cache. So for example if you load User by email ( which is naturalid), you will get only the primary key id from db, and the user object from first level cache if it is already there. So faster load time as less network data transfer.
As I explained in this article, the major advantage is that you can use the Cache to resolve the entity without hitting the database.
When the ResolveNaturalIdEvent event is thrown, Hibernate will try to:
fall-back to a database query if the 1st level cache can't satisfy our request
So, it's the same benefit as with using the entity loading through the Persistence Context API (e.g. EntityManager.find()).
The only time when two queries are executed is when the entity is not already cached (1st or 2nd level cache).