Add Hibernate 7 batches 2-6: mapping styles, JPA annotations, natural IDs, @Immutable, stored procedures, in-memory test databases, JNDI mocking, proxies, associations, temporal mapping, named queries, HQL, Criteria API and EntityManager bootstrapping (Hibernate 7.4.5.Final + Spring Boot 4.1.1 + JDK 25)

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EQNA6DJ9VgCtW6zhCE8Xud
This commit is contained in:
2026-09-18 18:23:51 +00:00
committed by Claude
co-authored by Claude Sonnet 5
commit 98bb6b4ce4
246 changed files with 19120 additions and 0 deletions
@@ -0,0 +1,84 @@
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 java.util.HashSet;
import java.util.Set;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
/**
* Does the "base equals()/hashCode() on the natural id, not the surrogate id" advice from
* posts 4864/4865 actually hold up? Reproduces the SAME HashSet-before-flush scenario as
* {@code IdBasedEqualsHashSetTrapTest} (persistenceannotations package) but with natural-id-based
* equals/hashCode instead of surrogate-id-based -- this time contains() should stay TRUE.
*
* <p>Docs: docs/06-natural-ids.md, Topic 3.
*/
@SpringBootTest(classes = HibernateDemoApplication.class)
class NaturalIdEqualsHashSetTest {
@Autowired
private EntityManagerFactory emf;
@Test
void naturalIdBasedEquals_addedToSetBeforeFlush_containsStaysTrueAfterPersist() {
Set<NaturalIdEqualsEntity> set = new HashSet<>();
NaturalIdEqualsEntity e = new NaturalIdEqualsEntity("SKU-EQ-1", "widget");
set.add(e); // sku is already set -- hashCode() is stable from construction
assertThat(set.contains(e)).isTrue();
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(e);
em.getTransaction().commit(); // id gets assigned, but sku (and hence hashCode) never changes
em.close();
boolean stillFound = set.contains(e);
System.out.println("RESULT[naturalid-equals-hashset]: after persist(), e.getId()=" + e.getId()
+ ", e.getSku()=" + e.getSku() + ", set.contains(e) = " + stillFound
+ " (equals/hashCode based on the immutable natural id, NOT the surrogate id)");
assertThat(stillFound)
.as("natural-id-based equals/hashCode must survive persist() -- the advice holds up, unlike the surrogate-id version")
.isTrue();
}
@Test
void naturalIdBasedEquals_twoTransientInstancesWithDifferentSkus_areNotEqual() {
NaturalIdEqualsEntity a = new NaturalIdEqualsEntity("SKU-EQ-A", "Widget A");
NaturalIdEqualsEntity b = new NaturalIdEqualsEntity("SKU-EQ-B", "Widget B");
// Unlike surrogate-id equals (where two transient instances are BOTH "equal" because
// both ids are null), natural-id equals correctly distinguishes them even before persist.
System.out.println("RESULT[naturalid-equals-transient]: a.equals(b) for two DIFFERENT transient instances = "
+ a.equals(b) + " (both have null surrogate ids, but different natural ids)");
assertThat(a).isNotEqualTo(b);
}
@Test
void naturalIdBasedEquals_twoTransientInstancesWithSameSku_areEqual_evenBeforePersist() {
// This is the flip side worth knowing: TWO DIFFERENT transient objects representing
// the "same" business entity (same sku, not yet persisted) are already equal() to
// each other, well before either has a database identity. That is usually desirable,
// but it means a HashSet can silently dedupe two not-yet-persisted objects.
NaturalIdEqualsEntity a = new NaturalIdEqualsEntity("SKU-EQ-DUP", "First instance");
NaturalIdEqualsEntity b = new NaturalIdEqualsEntity("SKU-EQ-DUP", "Second instance, different name");
Set<NaturalIdEqualsEntity> set = new HashSet<>();
set.add(a);
boolean bWasRejectedAsADuplicate = !set.add(b);
System.out.println("RESULT[naturalid-equals-transient-dup]: a.equals(b)=" + a.equals(b)
+ " for two transient instances sharing sku='SKU-EQ-DUP' but different names; "
+ "HashSet.add(b) rejected it as a duplicate = " + bWasRejectedAsADuplicate);
assertThat(a).isEqualTo(b);
assertThat(bWasRejectedAsADuplicate).isTrue();
}
}