Add Hibernate 7 batches 2-6, batch 7, and batch 8: mapping styles, JPA annotations, natural IDs, @Immutable, stored procedures, in-memory test databases, JNDI mocking, proxies, associations, temporal mapping, named queries, HQL, Criteria API, EntityManager bootstrapping, Ehcache 3 L2 cache configuration, HikariCP connection pooling, Hibernate Validator CDI integration, aggregate functions, sorting, pagination, interceptors, and Hibernate Search 8 (Hibernate 7.4.5.Final + Spring Boot 4.1.1 + JDK 25)
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
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.
|
||||
*
|
||||
* <p>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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user