112 lines
4.3 KiB
Java
Executable File
112 lines
4.3 KiB
Java
Executable File
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);
|
|
}
|
|
}
|