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,59 @@
package com.ankurm.hibernatedemo.persistenceannotations;
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;
/**
* The concrete failure: an entity with id-based equals()/hashCode() is added to a HashSet
* BEFORE flush (id == null), then persisted (id gets assigned). The same reference, looked up
* in the SAME set, is no longer found -- because its hash code changed after insertion, so
* HashSet is now probing the wrong bucket.
*
* <p>Docs: docs/05-jpa-persistence-annotations.md, Topic 2.
*/
@SpringBootTest(classes = HibernateDemoApplication.class)
class IdBasedEqualsHashSetTrapTest {
@Autowired
private EntityManagerFactory emf;
@Test
void idBasedEquals_addedToSetBeforeFlush_containsReturnsFalseAfterIdAssigned() {
Set<IdBasedEqualsEntity> set = new HashSet<>();
IdBasedEqualsEntity e = new IdBasedEqualsEntity("widget");
set.add(e); // id is null at this point -- hashCode() = Objects.hash((Long) null)
assertThat(set.contains(e)).isTrue(); // trivially true right now
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(e);
em.getTransaction().commit(); // id gets assigned HERE -- hashCode() changes
em.close();
assertThat(e.getId()).isNotNull();
boolean stillFound = set.contains(e);
System.out.println("RESULT[id-based-equals-hashset-trap]: after persist(), e.getId()=" + e.getId()
+ ", set.contains(e) = " + stillFound + " (same reference, same set, only the hash code changed)");
assertThat(stillFound)
.as("HashSet.contains() on the SAME reference must return false once the id-based hashCode changed after insertion")
.isFalse();
// Bonus: iterating the set and calling equals() manually still finds it (equals() itself is fine) --
// it's specifically the bucket lookup (which trusts the now-stale cached hash) that is broken.
boolean foundByIteration = set.stream().anyMatch(x -> x.equals(e));
System.out.println("RESULT[id-based-equals-hashset-trap]: manual iteration foundByIteration = " + foundByIteration
+ " -- confirms equals() itself still works; it's HashSet's bucket indexing that is now wrong.");
assertThat(foundByIteration).isTrue();
}
}