Yes, I was noticing different behaviors of those two caches.
(1) 2nd level cache can only optimize the simplest SQL like this
Code:
select * from tableName where primaryKey = ?
This is useful for
* org.hibernate.Session.get,
* org.hibernate.Session.load,
* javax.persistence.EntityManager.find,
* javax.persistence.ENtityManager.load
* The loading of many-to-one property, thats why I said it's the reason why "@javax.persistence.ManyToOne" dares to use FetchType.EAGER to be its default value.
(2) Query Cache, it's more complex and more smart, because it's designed for complex SQL,
For example, if you want to load child object,
* if collection property is one-to-many, the collection loading SQL should be
Code:
select * from childTable where foreignKeyToParentTable = ?
* if collection property is many-to-many, the collection loading SQL should be
Code:
select * from thisTable
inner join middleTable on thisTable.primaryKey = middleTable.foreignKeyToThis
where middleTable.foreignKeyToThat = ?
These SQLs are more complex, so only Query cache can help you.