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:
+111
@@ -0,0 +1,111 @@
|
||||
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.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
/**
|
||||
* What actually happens if you mutate a {@code @NaturalId} field Hibernate believes is
|
||||
* immutable (the default), versus one explicitly marked {@code mutable = true}?
|
||||
*
|
||||
* <p>Docs: docs/06-natural-ids.md, Topic 3.
|
||||
*/
|
||||
@SpringBootTest(classes = HibernateDemoApplication.class)
|
||||
class NaturalIdMutabilityTest {
|
||||
|
||||
@Autowired
|
||||
private EntityManagerFactory emf;
|
||||
|
||||
@Test
|
||||
void mutatingAnImmutableNaturalId_throwsOnFlush() {
|
||||
EntityManager em = emf.createEntityManager();
|
||||
em.getTransaction().begin();
|
||||
ImmutableNaturalIdEntity e = new ImmutableNaturalIdEntity("CODE-A");
|
||||
em.persist(e);
|
||||
em.getTransaction().commit();
|
||||
Long id = e.getId();
|
||||
em.close();
|
||||
|
||||
EntityManager em2 = emf.createEntityManager();
|
||||
Session session = em2.unwrap(Session.class);
|
||||
session.getTransaction().begin();
|
||||
ImmutableNaturalIdEntity managed = session.find(ImmutableNaturalIdEntity.class, id);
|
||||
managed.setCode("CODE-B"); // mutate the field Hibernate believes is immutable
|
||||
|
||||
HibernateException ex = org.junit.jupiter.api.Assertions.assertThrows(
|
||||
HibernateException.class,
|
||||
() -> {
|
||||
session.flush();
|
||||
});
|
||||
System.out.println("RESULT[naturalid-immutable-mutation]: flushing a changed IMMUTABLE natural id threw: "
|
||||
+ ex.getClass().getName() + ": " + ex.getMessage());
|
||||
session.getTransaction().rollback();
|
||||
em2.close();
|
||||
|
||||
assertThat(ex.getMessage()).containsIgnoringCase("immutable");
|
||||
}
|
||||
|
||||
@Test
|
||||
void mutatingAMutableNaturalId_flushesFine_andUpdatesTheColumn() {
|
||||
EntityManager em = emf.createEntityManager();
|
||||
em.getTransaction().begin();
|
||||
MutableNaturalIdEntity e = new MutableNaturalIdEntity("CODE-X");
|
||||
em.persist(e);
|
||||
em.getTransaction().commit();
|
||||
Long id = e.getId();
|
||||
em.close();
|
||||
|
||||
EntityManager em2 = emf.createEntityManager();
|
||||
em2.getTransaction().begin();
|
||||
MutableNaturalIdEntity managed = em2.find(MutableNaturalIdEntity.class, id);
|
||||
managed.setCode("CODE-Y");
|
||||
em2.getTransaction().commit(); // should NOT throw
|
||||
em2.close();
|
||||
|
||||
EntityManager em3 = emf.createEntityManager();
|
||||
Object raw = em3.createNativeQuery(
|
||||
"select code from mutable_natural_id_entity where id = " + id).getSingleResult();
|
||||
em3.close();
|
||||
|
||||
System.out.println("RESULT[naturalid-mutable-mutation]: flush succeeded, DB column now = " + raw);
|
||||
assertThat(raw).isEqualTo("CODE-Y");
|
||||
}
|
||||
|
||||
@Test
|
||||
void mutatingAMutableNaturalId_staleLookupByOldValue_noLongerResolves() {
|
||||
EntityManager em = emf.createEntityManager();
|
||||
em.getTransaction().begin();
|
||||
MutableNaturalIdEntity e = new MutableNaturalIdEntity("CODE-OLD");
|
||||
em.persist(e);
|
||||
em.getTransaction().commit();
|
||||
Long id = e.getId();
|
||||
em.close();
|
||||
|
||||
EntityManager em2 = emf.createEntityManager();
|
||||
em2.getTransaction().begin();
|
||||
MutableNaturalIdEntity managed = em2.find(MutableNaturalIdEntity.class, id);
|
||||
managed.setCode("CODE-NEW");
|
||||
em2.getTransaction().commit();
|
||||
em2.close();
|
||||
|
||||
EntityManager em3 = emf.createEntityManager();
|
||||
Session session = em3.unwrap(Session.class);
|
||||
MutableNaturalIdEntity byOld = session.bySimpleNaturalId(MutableNaturalIdEntity.class).load("CODE-OLD");
|
||||
MutableNaturalIdEntity byNew = session.bySimpleNaturalId(MutableNaturalIdEntity.class).load("CODE-NEW");
|
||||
em3.close();
|
||||
|
||||
System.out.println("RESULT[naturalid-mutable-stale-lookup]: byNaturalId(\"CODE-OLD\") = " + byOld
|
||||
+ ", byNaturalId(\"CODE-NEW\") = " + (byNew == null ? "null" : byNew.getId()));
|
||||
|
||||
assertThat(byOld).isNull();
|
||||
assertThat(byNew).isNotNull();
|
||||
assertThat(byNew.getId()).isEqualTo(id);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user