home
›
cheatsheets
›
backend_development
›
hibernate
Free to read Every card and diagram, and Quiz me
2
Free account Star cards. Your Quiz me marks are kept, so next time you drill just what you missed
3
Pro All 42 answers on this sheet, My sheet across every topic, and PDFs
A free account keeps your stars and Quiz me marks. Pro adds all 42 answers on this sheet, My sheet across every topic, and PDFs.
/
Read
Quiz me
Comfortable
Compact
My misses 0
Click any code to copy it
Done 0 /0
To review 0
Removed by Hibernate 7, still asked
Current API
Newer, Hibernate 6 or later
On this sheet
The model
01 Hibernate, JPA & setup02 Sessions & entity states03 Map classes to tables04 Associations & cascade05 Lazy loading & N+106 HQL, Criteria & filters07 First & second-level cache08 Transactions & locking09 Bulk work & performance10 Schema, audit & services
The model Hibernate is an ORM on top of JDBC. It maps objects to tables and writes the SQL. It implements JPA , now Jakarta Persistence, the standard API. A SessionFactory is built once and shared by all threads. A Session is one unit of work. It isn't thread-safe, so each request gets its own. The session's persistence context tracks every entity it loads. That's the first-level cache, so loading a row twice returns the same object. At flush , dirty checking compares each tracked entity with its snapshot and writes the changes. You make no save call. A lazy association loads on first use and needs an open session. N+1 queries and LazyInitializationException both start here. Only a persistent entity is tracked. After remove(), it stays in the removed state until flush deletes its row.
Hibernate, JPA & setup what Hibernate is and how it starts Configure Hibernate Use a file on the classpath hibernate.cfg.xml hibernate.properties
Set it in code, or start through JPA new Configuration() persistence.xml
Tip Hibernate detects the dialect from JDBC metadata, so that setting is usually optional.
JDBC, Hibernate or JPA Control every statement by hand JDBC. You write the SQL and map the results.
Map a large model of related entities Hibernate. It writes the SQL and maps rows to objects.
Keep the option to switch providers Use only JPA, with EntityManager and JPQL.
Use filters, @BatchSize or custom types Use Hibernate's own features. They tie you to it.
Tip Hibernate adds caching, and HQL that runs on any supported database. Session extends JPA's EntityManager.
Core types Read settings and build the factory Configuration
Create sessions and hold the second-level cache SessionFactory
Do one unit of work, on one thread Session
Begin, commit or roll back Transaction
Run a query, or build one in code Query CriteriaBuilder
Trap Build the SessionFactory once at startup, because it's expensive. Open a Session per request or thread, and close it.
Sessions & entity states what the session tracks and when it writes Entity states Detach entities by closing the session close()
Delete the row at the next flush remove(user)
Tip A new object is transient. A persistent object is also called managed, and the session saves its changes.
save, persist or saveOrUpdate Save and get the id back save(user)
Save a new object, and return nothing persist(user)
Save or update, after checking the id saveOrUpdate(user)
Tip Hibernate 7 removed save() and saveOrUpdate(). Use persist(), or merge() for a detached object.
Trap With an identity column, save() inserts at once, even outside a transaction. persist() never does.
merge or update Reattach the object you pass update(user)
Copy a detached object onto a managed one managed = merge(user)
Tip update() throws if the session already holds that id. Hibernate 7 removed it.
Trap merge() leaves your object detached. Keep using the one it returns.
get or load Load the row now, or get null find(User.class, id) get(User.class, id)
Get a proxy, with no SELECT yet getReference(User.class, id)
Do the same before Hibernate 7 load(User.class, id)
Tip A proxy sets a foreign key without loading the row, as in order.setUser(ref) .
Trap A proxy fails later on a missing row. Its first use throws ObjectNotFoundException .
openSession or getCurrentSession Get a new session, and close it yourself openSession()
Get the one bound to this context getCurrentSession() It needs an active transaction, and Hibernate closes it at the end.
Tip hibernate.current_session_context_class sets the context to thread or jta.
Trap Neither is thread-safe. A bound session is safe only because each thread or transaction gets its own.
Dirty checking Save a change to a tracked entity user.setName("New") No save call. Flush compares it with the snapshot.
Update only the changed columns @DynamicUpdate Hibernate then builds the SQL at runtime.
Tip By default, the UPDATE sets every mapped column, so one cached statement serves all updates.
Flush modes Commit Query
AUTO Keep queries correct, the default
COMMIT Run faster, accept stale results
MANUAL Flush only when you call flush()
ALWAYS Flush before every query
flushes before it doesn't flush
Tip AUTO flushes only before a query the changes could affect. Set a mode with setHibernateFlushMode() .
Trap By default, Hibernate doesn't flush before a native SQL query.
Sessions in a web app Handle a web request Session per request, with one transaction.
Span several requests Session per conversation, with @Version.
Stop lazy queries in the web layer spring.jpa.open-in-view=false
Tip After an exception, roll back and discard the session. It's no longer usable.
Trap Never share one session across the app. It isn't thread-safe, and its cache keeps growing.
Map classes to tables annotations for entities, values and keys Entity annotations Map a class to a table @Entity @Table(name = "users")
Mark the primary key @Id @GeneratedValue
Rename a column, or leave a field out @Column(name = "x") @Transient
Tip Without @Table, the table takes the entity's name.
Trap An entity needs an @Id and a no-argument constructor that isn't private. The class can't be final.
Value types and composite keys Define a value type, and hold it in a field @Embeddable @Embedded
Rename columns to embed a type twice @AttributeOverride
Keep a composite key in one field @EmbeddedId
Keep each key column as its own @Id field @IdClass(RoleId.class)
Tip A value type has no table and no id. Its fields become columns in the entity's table. @Embedded is optional.
Trap A key class must be Serializable, have a no-argument constructor, and override equals() and hashCode().
Inheritance strategies Put the whole hierarchy in one table SINGLE_TABLE The default, usually fastest, with a discriminator column.
Normalize, with one table per class JOINED Loading joins the tables, so queries are slower.
Give each concrete class a full table TABLE_PER_CLASS A query on the parent needs a UNION.
Tip Choose it with @Inheritance. One table can waste space on subclass columns.
Custom types Convert a simple value @Convert Write a JPA AttributeConverter .
Control how JDBC reads and writes a value @Type(MyType.class) Implement UserType, or CompositeUserType for several columns.
Trap A UserType from Hibernate 5 doesn't compile on 6, and 7 changed nullSafeGet() and nullSafeSet() again.
Naming strategies Change every name sent to the database PhysicalNamingStrategy
Pick a name when no annotation gives one ImplicitNamingStrategy
Get snake case with no custom code PhysicalNamingStrategySnakeCaseImpl
Tip Register yours in hibernate.physical_naming_strategy .
equals and hashCode Base them on an immutable business key @NaturalId Add a unique constraint too.
Compare types so a proxy still matches o instanceof Book b A proxy is a subclass, so getClass() fails.
Trap A generated id is null until Hibernate persists the entity. A hash code built on it changes, and a HashSet loses the entity.
Associations & cascade link entities and pass operations on to children Association mappings In User, the inverse side @OneToMany(mappedBy = "user") private List<Order> orders; In Order, the owning side @ManyToOne @JoinColumn(name = "user_id") private User user;
Map the other two kinds @OneToOne @ManyToMany
Trap In a bidirectional link, Hibernate writes only changes made on the owning side. A change to the mappedBy side alone writes nothing.
Cascade types Persist or merge children with the parent PERSIST MERGE
Delete children with the parent REMOVE
Reload or detach children too REFRESH DETACH
Apply all of the above ALL
Delete a child removed from the collection orphanRemoval = true
Tip Set them with CascadeType. Cascade fits a parent that owns its children.
Trap Avoid REMOVE and ALL on @ManyToMany. Removing one entity deletes rows that other entities still use.
Lazy loading & N+1 load what you use, in as few queries as you can Lazy or eager Load on first access, the to-many default @OneToMany @ManyToMany
Load with the parent, the to-one default @ManyToOne @OneToOne
Make a to-one association lazy fetch = FetchType.LAZY
Tip Make almost every association lazy. Fetch what a use case needs with a join fetch or an entity graph.
Fix the N+1 problem lazy loop @BatchSize subselect join fetch Getting the orders of 5 users. Each bar is one query, and the dark one loads the users. A lazy loop sends 6, a batch size of 2 sends 4, a fetch join 1.
Load users and orders in one query LEFT JOIN FETCH u.orders
Load several users' orders per query @BatchSize(size = 10)
Load all collections with one extra query @Fetch(FetchMode.SUBSELECT)
Tip A lazy association read in a loop causes it. A JPA entity graph also fixes it, by naming what to fetch.
Fix LazyInitializationException Fetch it in the query join fetch o.items
Load it inside the transaction Hibernate.initialize(o.getItems())
Send only the fields the caller uses Use a DTO projection.
Tip The cause is code reading a lazy field after its session closed, often in a controller or a JSON serializer.
Trap EAGER and Open Session in View only hide it. EAGER loads on every query, and the view runs extra lazy queries.
HQL, Criteria & filters ask for entities, not tables HQL and native SQL Query entities, not tables FROM User u WHERE u.name = :n
Use a database-specific feature createNativeQuery(sql)
Page through results setFirstResult(20) setMaxResults(10)
Tip HQL is a superset of JPQL. A query on a parent class also returns its subclasses.
Trap Class and property names are case-sensitive in HQL. Keywords such as select aren't.
Criteria or Query by Example Add conditions at runtime getCriteriaBuilder() It also does joins and grouping. The JPA metamodel makes it type-safe.
Match the fields set on an example object Example.of(user) It can't nest or group conditions.
Use Hibernate's own Criteria API org.hibernate.criterion Hibernate 6.0 removed it, with its Example class.
Trap Example.of() is from Spring Data JPA, not Hibernate.
Filters Declare a filter and its parameters @FilterDef
Attach the SQL condition to the entity @Filter
Turn it on for this session enableFilter("active")
Tip A new session starts with every filter off.
Trap By default, filters don't apply to find() or to @ManyToOne associations. Set applyToLoadByKey (6.6+) to include them.
First & second-level cache skip the database when the data hasn't changed Cache levels Share entities across sessions @Cache @Cacheable
Turn the second level on hibernate.cache.use_second_level_cache=true
Cache query results hibernate.cache.use_query_cache=true
Tip The first level ends with its session. The second level suits data read often and changed rarely.
Trap The query cache is rarely worth it. Any change to a queried table clears its results.
Second-level strategies and providers Cache data that never changes READ_ONLY
Cache with no locks NONSTRICT_READ_WRITE
Cache with soft locks READ_WRITE
Use a fully transactional provider TRANSACTIONAL
Cache on a single node Caffeine, a fast local cache.
Share the cache across nodes Hazelcast, Infinispan or a clustered Ehcache.
Tip Hibernate has no second-level cache of its own. Most providers plug in through JCache, with hibernate-jcache.
Transactions & locking keep concurrent transactions correct Optimistic locking Catch conflicting updates without row locks @Version
Handle a conflict in the service layer OptimisticLockException Reload and retry, or show the conflict.
Lock the row when conflicts are frequent SELECT ... FOR UPDATE This is pessimistic locking.
Tip Hibernate adds the old version to the WHERE clause. If another transaction changed the row, no row matches and Hibernate throws.
Isolation levels Dirty New value New row
READ_UNCOMMITTED Allow all three read problems
READ_COMMITTED Stop dirty reads
REPEATABLE_READ Also stop non-repeatable reads
SERIALIZABLE Also stop phantom reads
prevented can happen
Tip A dirty read sees uncommitted data, a non-repeatable read a new value, and a phantom read new rows. Set the level with @Transactional(isolation = ...).
Trap Higher levels hold more locks or abort more transactions, so throughput drops.
Schema, audit & services what senior interviews add Schema changes Check the schema at startup, change nothing validate
Add what's missing, in development update
Recreate the tables at startup, or drop them at close create create-drop
Change a production schema Use Flyway or Liquibase, with validate.
Tip Set hibernate.hbm2ddl.auto to one of these values.
Trap Never use create or create-drop against production data. They drop the existing tables.
Audit with Envers Record every change in an audit table @Audited
Leave a field out of the history @NotAudited
Query the revisions AuditReaderFactory.get(session)
Use the audit support in ORM itself (7.4+) @org.hibernate.annotations.Audited
Trap Envers records passwords unless they're @NotAudited.
Interceptors and event listeners Use one object with a callback per operation Interceptor
Use one handler per lifecycle event PreInsertEventListener
Tip An interceptor can fill audit columns. Its onPersist() returns true only when it changed the state array.
Multi-tenancy Give each tenant its own database Strongest isolation, but the most databases to run.
Give each tenant its own schema MultiTenantConnectionProvider
Share tables, with a tenant column (6+) @TenantId
Tell Hibernate the current tenant CurrentTenantIdentifierResolver
Trap Native SQL queries aren't filtered by tenant. Add the condition yourself.
Hibernate in microservices Keep data inside one service One database per service, and no other service reads it.
Change data across services Use events and a saga, with eventual consistency. A Hibernate transaction covers one database.
Send data between services Send DTOs, never entities.
Trap Many instances multiply the connections a database must hold. Size each pool for its service's load.
Nothing matches. Try a shorter word, or clear the search.
Practice 42 interview questions Full answers, from beginner to expert.
Found this useful? Pass it on.
Share on LinkedIn
Share on X
Copy link
This sheet stays free. With Pro , you can:
Every answer on this sheet. Read the full answer to all 42 questions it links, not just the 5 free ones.
My sheet. The cards you star and the ones you miss in Quiz me, from every sheet, on one page to quiz and print.
PDFs. Download this sheet and My sheet, laid out for A4, with every question a link to its answer.
The rest of Pro. Every answer in the question library, and 1,000 AI credits a month.