Most developers who have used Hibernate for any length of time know the first-level cache exists. Ask them to describe it and you’ll hear something like: “It’s a cache Hibernate uses so it doesn’t hit the database twice for the same row.” That’s technically correct, but it misses almost everything that matters.
The first-level cache is not a feature you enable, a setting you tune, or an optional layer you bolt on for performance. It is the persistence context itself — always-on, transaction-scoped by default in Spring, and the thing that makes dirty checking, identity guarantees, and cascade operations possible. If you have ever used em.find(), you have used it. If you have ever hit an OutOfMemoryError in a batch job that loaded 200,000 entities, the first-level cache is why.
This post is a deep look at the mechanics: what the persistence context stores, when it is consulted, how EntityKey works, and the failure modes that catch experienced developers off guard.