13 minutes / published

The Hibernate Mental Model: Persistence Context, Proxies, and @Transactional

Entity states, lazy boundaries, dirty checking, and transaction proxies made visible through tests.

Start With The Persistence Context

The most useful Hibernate sentence is simple: inside one persistence context, one database row has one managed Java object.

That rule explains identity surprises, dirty checking, and why a detached object feels ordinary until you ask Hibernate to manage it again.

Dirty Checking Is A Unit-Of-Work Story

The course test renames a managed cinema, flushes, and reloads it. The emitted UPDATE is not magic; it is Hibernate comparing managed state at flush time.

That behavior is powerful only when the transaction boundary is clear enough for reviewers to predict.

Lazy Loading Is A Boundary

LazyInitializationException is not a random Hibernate tax. It is a signal that code crossed a persistence boundary and still expected database access.

Phase 2B keeps the exception as a teaching artifact so learners can recognize it before production logs teach it under pressure.

Proxies Are Why Self-Invocation Matters

@Transactional is applied through a proxy. Calling another method on this bypasses that proxy, so propagation and rollback assumptions can be wrong even when annotations look correct.

The transcript names that trap beside read-only transaction behavior so the article stays grounded in code rather than folklore.

Boot 3 To 4 Delta

The package names are Jakarta-era and the dependency set is Boot 4 shaped, but the persistence context, dirty checking, proxy, and lazy-loading lessons are the same senior debugging skills.

That is the point: framework currency matters, but the mental model is what transfers.