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,51 @@
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 org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
/**
* MixedAccessEntity has FIELD access by default (because @Id sits on a field), but one
* property ("computedLabel") is explicitly switched to PROPERTY access. This proves:
* (1) Hibernate really does call the getter -- not read a backing field -- to determine the
* persisted value for that one property, and (2) it calls it MORE than once per flush
* (dirty-check read + write), which matters if the getter has side effects or is expensive.
*
* <p>Docs: docs/05-jpa-persistence-annotations.md, Topic 2.
*/
@SpringBootTest(classes = HibernateDemoApplication.class)
class MixedAccessTest {
@Autowired
private EntityManagerFactory emf;
@Test
void propertyAccessAttribute_getterIsCalledByHibernate_multipleTimesPerFlush() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
MixedAccessEntity e = new MixedAccessEntity("widget");
int callsBeforePersist = e.getGetterCallCount();
em.persist(e);
em.getTransaction().commit();
Long id = e.getId();
int callsAfterFlush = e.getGetterCallCount();
em.close();
System.out.println("RESULT[mixed-access]: getComputedLabel() call count before persist=" + callsBeforePersist
+ ", after commit/flush=" + callsAfterFlush
+ " (PROPERTY-access attributes are read via the getter at flush time, not via a backing field)");
assertThat(callsAfterFlush).isGreaterThan(callsBeforePersist);
EntityManager em2 = emf.createEntityManager();
Object storedLabel = em2.createNativeQuery(
"select computed_label from mixed_access_entity where id = " + id).getSingleResult();
em2.close();
System.out.println("RESULT[mixed-access]: DB column computed_label = " + storedLabel);
assertThat(storedLabel).isEqualTo("WIDGET");
}
}