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:
2026-09-20 06:06:42 +00:00
committed by Claude
commit 8568c0ce6c
330 changed files with 23668 additions and 0 deletions
@@ -0,0 +1,94 @@
package com.ankurm.hibernatedemo.testdb;
import static org.assertj.core.api.Assertions.assertThat;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Backs docs/09-testing-in-memory-databases.md, chapter "Schema isolation: create-drop vs rollback vs
* DB_CLOSE_DELAY". Uses one shared {@link EntityManagerFactory} across two ordered tests to
* PROVE the pollution, then a second, correctly-isolated pair to prove the fix -- both against
* plain H2 (the pollution mechanism is not H2-specific, but H2 is what the rest of this repo
* already uses for its default datasource).
*/
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class SchemaIsolationTest {
private static final Logger DEMO = LoggerFactory.getLogger("DEMO");
private static SessionFactory pollutedSf;
@BeforeAll
static void openSharedFactory() {
// DB_CLOSE_DELAY=-1 is what keeps this in-memory H2 database alive across the many
// short-lived connections each Session opens and closes -- without it, H2 tears the
// whole in-memory database down the moment the LAST open connection closes, and the
// next openSession() call would silently reconnect to a brand-new, empty database
// instead of failing loudly.
pollutedSf = TestDbSupport.buildSessionFactory(
TestDbSupport.Db.H2, "isolation-demo", "create-drop", TestDbWidget.class);
}
@AfterAll
static void closeSharedFactory() {
pollutedSf.close();
}
@Test
@Order(1)
void testA_insertsARowWithNoCleanup() {
Session session = pollutedSf.openSession();
session.beginTransaction();
session.persist(new TestDbWidget("AAAAA", 1, true, "left behind by testA"));
session.getTransaction().commit();
session.close();
DEMO.info("testA committed a row and did nothing to clean it up");
}
@Test
@Order(2)
void testB_seesTestAsRow_becauseThereWasNoIsolationBetweenThem() {
Session session = pollutedSf.openSession();
long count = session.createQuery("select count(w) from TestDbWidget w", Long.class).getSingleResult();
session.close();
DEMO.info("testB sees {} row(s) -- at least one is testA's leftover, proving pollution when isolation is skipped", count);
// The point: testB did not insert anything itself yet, but the row count is already
// >= 1, because testA's commit was never rolled back or dropped.
assertThat(count).isGreaterThanOrEqualTo(1);
}
// ---- Now the same shape, but done correctly with @Transactional-style manual rollback ----
@Test
@Order(3)
void testC_insertsARow_thenRollsBackInsteadOfCommitting() {
Session session = pollutedSf.openSession();
session.beginTransaction();
session.persist(new TestDbWidget("BBBBB", 2, true, "rolled back by testC, must not survive"));
long duringTxn = session.createQuery("select count(w) from TestDbWidget w", Long.class).getSingleResult();
session.getTransaction().rollback();
session.close();
DEMO.info("testC saw {} row(s) DURING its own transaction (includes its own uncommitted insert), then rolled back", duringTxn);
}
@Test
@Order(4)
void testD_doesNotSeeTestCsRolledBackRow() {
Session session = pollutedSf.openSession();
long count = session.createQuery(
"select count(w) from TestDbWidget w where w.sku = :sku", Long.class)
.setParameter("sku", "BBBBB")
.getSingleResult();
session.close();
DEMO.info("testD looks specifically for testC's SKU 'BBBBB' -- found {} (must be 0: rollback isolated it)", count);
assertThat(count).isZero();
}
}