Deliberately plain JUnit, NOT {@code @SpringBootTest} -- the whole point of this chapter is
* bootstrapping a raw JPA {@link EntityManagerFactory} with no Spring involved, exactly as a
* Java SE application or a unit test outside a Spring context would. The XML path reads
* {@code src/test/resources/META-INF/persistence.xml}; the programmatic path uses Jakarta
* Persistence 3.2's {@link PersistenceConfiguration}, new in this version.
*
*
Run with {@code ./mvnw -Dtest=EntityManagerBootstrapTest test}.
*/
class EntityManagerBootstrapTest {
private static final Logger DEMO = LoggerFactory.getLogger("DEMO");
@Test
void xmlBootstrap_createsFactoryFromPersistenceXmlAndPersistsAUser() {
// No properties map passed here at all -- everything comes from
// META-INF/persistence.xml on the test classpath, resolved purely by unit name.
try (EntityManagerFactory emf = Persistence.createEntityManagerFactory("XmlBootstrapPU")) {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
BootstrapUser user = new BootstrapUser("Ankur", "admin@ankurm.com");
em.persist(user);
em.getTransaction().commit();
Long id = user.getId();
em.close();
EntityManager reader = emf.createEntityManager();
BootstrapUser reloaded = reader.find(BootstrapUser.class, id);
assertThat(reloaded).isNotNull();
assertThat(reloaded.getEmail()).isEqualTo("admin@ankurm.com");
reader.close();
DEMO.info("xmlBootstrap: persisted and reloaded user id={}", id);
}
}
@Test
void programmaticBootstrap_needsNoPersistenceXmlUnitOnClasspath() {
// "ProgrammaticPU" has NO matching anywhere in persistence.xml --
// this only works at all if PersistenceConfiguration genuinely bypasses XML lookup.
PersistenceConfiguration config = new PersistenceConfiguration("ProgrammaticPU")
.provider("org.hibernate.jpa.HibernatePersistenceProvider")
.managedClass(BootstrapUser.class)
.property(PersistenceConfiguration.JDBC_DRIVER, "org.h2.Driver")
.property(PersistenceConfiguration.JDBC_URL, "jdbc:h2:mem:bootstrap-programmatic;DB_CLOSE_DELAY=-1")
.property(PersistenceConfiguration.JDBC_USER, "sa")
.property(PersistenceConfiguration.JDBC_PASSWORD, "")
.property("hibernate.hbm2ddl.auto", "create-drop");
try (EntityManagerFactory emf = config.createEntityManagerFactory()) {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
BootstrapUser user = new BootstrapUser("Programmatic", "prog@ankurm.com");
em.persist(user);
em.getTransaction().commit();
Long id = user.getId();
em.close();
EntityManager reader = emf.createEntityManager();
assertThat(reader.find(BootstrapUser.class, id)).isNotNull();
reader.close();
DEMO.info("programmaticBootstrap: persisted user id={} with zero persistence.xml units named 'ProgrammaticPU'", id);
}
}
@Test
void persistenceUnitName_inProgrammaticConfig_doesNotTriggerXmlSearch() {
// Reusing "XmlBootstrapPU" -- the EXACT SAME name as the real XML unit -- but with
// completely different properties built purely in code, pointed at a third database.
// If the name alone triggered an XML lookup/merge, this factory would end up
// connected to bootstrap-xml (the XML unit's database) instead. It doesn't.
PersistenceConfiguration config = new PersistenceConfiguration("XmlBootstrapPU")
.provider("org.hibernate.jpa.HibernatePersistenceProvider")
.managedClass(BootstrapUser.class)
.property(PersistenceConfiguration.JDBC_DRIVER, "org.h2.Driver")
.property(PersistenceConfiguration.JDBC_URL, "jdbc:h2:mem:bootstrap-namecollision;DB_CLOSE_DELAY=-1")
.property(PersistenceConfiguration.JDBC_USER, "sa")
.property(PersistenceConfiguration.JDBC_PASSWORD, "")
.property("hibernate.hbm2ddl.auto", "create-drop");
try (EntityManagerFactory emf = config.createEntityManagerFactory()) {
EntityManager em = emf.createEntityManager();
@SuppressWarnings("unchecked")
java.util.List