The query cache stores IDs returned by previous executions of a cacheable select query.
Let's say you execute the following cacheable query:
select line from OrderLine line join line.order order
where line.status = ? and order.date = ?
If you execute it once, Hibernate will store the IDs of the lines returned by the query in its query cache. And it will store the lines themselves in the second-level cache.
If you execute the same query a second time, with the same parameters, Hibernate will extract the IDs from the query cache, without executing the select query. Then it will get every line by ID (which should be fast since the lines are in the second-level cache)
If you insert, update or delete a line or an order, Hibernate will detect it. Since this modification could affect the result of the cached query, the cache entries associated with this query in the query cache will be evicted. So the nexttime you execute this query again, it will be executed against the database, and the results will be stored again in the query cache.