ExerciseWarm-up
Warm-up
Find the queries you did not ask for
10 minjunior0–15 yrs
One concept, guided. Near-impossible to fail.
What this teaches
- To-one associations default to EAGER and collections default to LAZY
- Loading one entity and touching nothing can still issue several queries
- LazyInitializationException means an entity outlived its session
- open-in-view hides the exception by moving the queries into rendering
Starter
Starter.java
import java.util.*;
/**
* Warm-up: count the queries nobody asked for.
*
* A model of a persistence context — a session that opens and closes, proxies
* that throw when touched afterwards, and a counter. No Hibernate, because the
* behaviour worth learning is which associations load and when.
*/
public class Starter {
enum Fetch { LAZY, EAGER }
public static void main(String[] args) {
// TODO 1: write down, from memory, the default fetch type for
// @ManyToOne, @OneToOne, @OneToMany and @ManyToMany. Then check.
// Most people get two of the four wrong.
// TODO 2: build a Session with an open flag and a query counter, and
// an Association with a fetch type. EAGER records a query when it is
// constructed. LAZY records one on first access, and throws if the
// session has closed.
// TODO 3: build an Order with a to-one and a to-many, each using the
// JPA DEFAULT for its mapping. Load it. Touch nothing. Print the query
// count and which associations are loaded.
//
// Predict the number first.
// TODO 4: now load 100 orders the same way. What is the query count,
// and which annotation caused it? Note that nothing in the mapping
// says EAGER.
// TODO 5: make everything LAZY. Close the session, then read the
// collection. You should get your exception. Read the message — it
// says "no Session", which is the whole diagnosis.
// TODO 6: now keep the session open until after the read, the way
// spring.jpa.open-in-view does. The exception disappears. Count the
// queries issued BEFORE the session would normally have closed, and
// the queries issued after. Say which of those two numbers a timer
// around your service method would have seen.
// TODO 7: someone "fixes" the exception by making the collection
// EAGER. Compare the total query count against the open-in-view
// version. Say what actually changed and what did not.
// TODO 8: finally, load the collections deliberately before closing —
// one extra query for all of them. Compare all four numbers and say
// which is the fix and which two are hiding places.
// TODO 9: check what spring.jpa.open-in-view defaults to in Spring
// Boot, and find the warning it logs at startup.
}
}Run it locally:
cd exercises/java/jpa-hibernate/fetch-types/01-warmup
javac Starter.java -d /tmp/out && java -cp /tmp/out StarterDone when
- You showed a single entity load issuing more than one query
- You produced LazyInitializationException deliberately
- You showed the same code succeeding with the session kept open, and counted where the queries moved to
- You can state the default for all four mapping annotations without looking
← Back to What are the fetch types, and which is the default for each mapping?