Same logical operation — load every order for a customer and read every item on every order — run against identical H2 data, counted by the same StatementLoggingDataSource, for two stacks. orders items/ea JPA (no fetch join) Spring Data JDBC 1 1 2 2 1 5 2 2 5 1 6 6 5 5 6 6 20 3 21 21 JPA here uses plain findAll() + lazy .getItems() (scenario 02's shape); adding an @EntityGraph flattens the JPA column to a constant too (scenario 03). The point is not "JDBC beats JPA" in the abstract — it's that JDBC's default gives you the flattened shape for free, while JPA's default gives you the linear one, and the fix for JPA requires the reader to know it's needed.