package com.ankurm.hibernatedemo.naturalid; import static org.assertj.core.api.Assertions.assertThat; import com.ankurm.hibernatedemo.HibernateDemoApplication; import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManagerFactory; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.stat.Statistics; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; /** * THE central empirical question for post 4865: with NO second-level cache, does a * bySimpleNaturalId lookup save a query on a second call in the SAME session? Counted with * real Hibernate Statistics, not asserted from documentation. * *
Docs: docs/06-natural-ids.md, Topic 3. */ @SpringBootTest(classes = HibernateDemoApplication.class) class NaturalIdL1CacheTest { @Autowired private EntityManagerFactory emf; private Statistics stats() { return emf.unwrap(SessionFactory.class).getStatistics(); } @Test void bySimpleNaturalId_secondCallSameSession_noL2Cache_savesTheQuery() { EntityManager seedEm = emf.createEntityManager(); seedEm.getTransaction().begin(); seedEm.persist(new NaturalIdProduct("SKU-L1-1", "Widget")); seedEm.getTransaction().commit(); seedEm.close(); EntityManager em = emf.createEntityManager(); Session session = em.unwrap(Session.class); stats().clear(); NaturalIdProduct first = session.bySimpleNaturalId(NaturalIdProduct.class).load("SKU-L1-1"); long queriesAfterFirst = stats().getPrepareStatementCount(); NaturalIdProduct second = session.bySimpleNaturalId(NaturalIdProduct.class).load("SKU-L1-1"); long queriesAfterSecond = stats().getPrepareStatementCount(); em.close(); System.out.println("RESULT[naturalid-l1-no-l2]: queries after 1st bySimpleNaturalId=" + queriesAfterFirst + ", after 2nd (same session)=" + queriesAfterSecond + " (no @NaturalIdCache, no L2 cache provider configured)"); assertThat(queriesAfterFirst).isEqualTo(1); assertThat(queriesAfterSecond) .as("second bySimpleNaturalId call in the SAME session must NOT re-fire a query -- L1 natural-id resolution cache") .isEqualTo(1); assertThat(second).isSameAs(first); } @Test void bySimpleNaturalId_newSession_noL2Cache_reFiresTheQuery() { EntityManager seedEm = emf.createEntityManager(); seedEm.getTransaction().begin(); seedEm.persist(new NaturalIdProduct("SKU-L1-2", "Gadget")); seedEm.getTransaction().commit(); seedEm.close(); EntityManager em1 = emf.createEntityManager(); Session session1 = em1.unwrap(Session.class); stats().clear(); session1.bySimpleNaturalId(NaturalIdProduct.class).load("SKU-L1-2"); long queriesSession1 = stats().getPrepareStatementCount(); em1.close(); EntityManager em2 = emf.createEntityManager(); Session session2 = em2.unwrap(Session.class); session2.bySimpleNaturalId(NaturalIdProduct.class).load("SKU-L1-2"); long queriesAfterSession2 = stats().getPrepareStatementCount(); em2.close(); System.out.println("RESULT[naturalid-cross-session-no-l2]: queries after session 1 lookup=" + queriesSession1 + ", cumulative after a NEW session repeats the same lookup=" + queriesAfterSession2 + " (no L2 cache -- the L1 natural-id map dies with the session)"); assertThat(queriesAfterSession2) .as("without L2 cache, a brand-new session must re-fire the query -- the L1 mapping does not survive session close") .isEqualTo(queriesSession1 + 1); } }