Revise PersistenceUnitInfo management for compatibility with JPA 3.2/4.0

Closes gh-35622
This commit is contained in:
Juergen Hoeller
2025-10-13 14:23:31 +02:00
parent b4dcb36b21
commit d216236aac
11 changed files with 125 additions and 120 deletions
@@ -30,7 +30,6 @@ import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.EntityTransaction;
import jakarta.persistence.TransactionRequiredException;
import jakarta.persistence.spi.PersistenceUnitInfo;
import jakarta.persistence.spi.PersistenceUnitTransactionType;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
@@ -38,6 +37,7 @@ import org.jspecify.annotations.Nullable;
import org.springframework.core.Ordered;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.orm.jpa.persistenceunit.SmartPersistenceUnitInfo;
import org.springframework.transaction.support.ResourceHolderSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;
@@ -192,14 +192,13 @@ public abstract class ExtendedEntityManagerCreator {
* transactions (according to the JPA 2.1 SynchronizationType rules)
* @return the EntityManager proxy
*/
@SuppressWarnings("removal")
private static EntityManager createProxy(EntityManager rawEntityManager,
EntityManagerFactoryInfo emfInfo, boolean containerManaged, boolean synchronizedWithTransaction) {
Assert.notNull(emfInfo, "EntityManagerFactoryInfo must not be null");
JpaDialect jpaDialect = emfInfo.getJpaDialect();
PersistenceUnitInfo pui = emfInfo.getPersistenceUnitInfo();
Boolean jta = (pui != null ? pui.getTransactionType() == PersistenceUnitTransactionType.JTA : null);
Boolean jta = (pui instanceof SmartPersistenceUnitInfo spui ? spui.isConfiguredForJta() : null);
return createProxy(rawEntityManager, emfInfo.getEntityManagerInterface(),
emfInfo.getBeanClassLoader(), jpaDialect, jta, containerManaged, synchronizedWithTransaction);
}
@@ -134,7 +134,7 @@ public class DefaultPersistenceUnitManager
private final Set<String> persistenceUnitInfoNames = new HashSet<>();
private final Map<String, PersistenceUnitInfo> persistenceUnitInfos = new HashMap<>();
private final Map<String, SpringPersistenceUnitInfo> persistenceUnitInfos = new HashMap<>();
/**
@@ -620,26 +620,25 @@ public class DefaultPersistenceUnitManager
/**
* Return the specified PersistenceUnitInfo from this manager's cache
* of processed persistence units, keeping it in the cache (i.e. not
* 'obtaining' it for use but rather just accessing it for post-processing).
* Return the specified {@link MutablePersistenceUnitInfo} from this manager's cache
* of processed persistence units, keeping it in the cache (i.e. not 'obtaining' it
* for use but rather just accessing it for post-processing).
* <p>This can be used in {@link #postProcessPersistenceUnitInfo} implementations,
* detecting existing persistence units of the same name and potentially merging them.
* @param persistenceUnitName the name of the desired persistence unit
* @return the PersistenceUnitInfo in mutable form, or {@code null} if not available
*/
protected final @Nullable MutablePersistenceUnitInfo getPersistenceUnitInfo(String persistenceUnitName) {
PersistenceUnitInfo pui = this.persistenceUnitInfos.get(persistenceUnitName);
return (MutablePersistenceUnitInfo) pui;
return this.persistenceUnitInfos.get(persistenceUnitName);
}
/**
* Hook method allowing subclasses to customize each PersistenceUnitInfo.
* Hook method allowing subclasses to customize each {@link MutablePersistenceUnitInfo}.
* <p>The default implementation delegates to all registered PersistenceUnitPostProcessors.
* It is usually preferable to register further entity classes, jar files etc there
* rather than in a subclass of this manager, to be able to reuse the post-processors.
* @param pui the chosen PersistenceUnitInfo, as read from {@code persistence.xml}.
* Passed in as MutablePersistenceUnitInfo.
* @param pui the chosen persistence unit configuration, as read from
* {@code persistence.xml}. Passed in as MutablePersistenceUnitInfo.
* @see #setPersistenceUnitPostProcessors
*/
protected void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) {
@@ -674,14 +673,14 @@ public class DefaultPersistenceUnitManager
if (this.persistenceUnitInfos.size() > 1 && this.defaultPersistenceUnitName != null) {
return obtainPersistenceUnitInfo(this.defaultPersistenceUnitName);
}
PersistenceUnitInfo pui = this.persistenceUnitInfos.values().iterator().next();
SpringPersistenceUnitInfo pui = this.persistenceUnitInfos.values().iterator().next();
this.persistenceUnitInfos.clear();
return pui;
return pui.toSmartPersistenceUnitInfo();
}
@Override
public PersistenceUnitInfo obtainPersistenceUnitInfo(String persistenceUnitName) {
PersistenceUnitInfo pui = this.persistenceUnitInfos.remove(persistenceUnitName);
SpringPersistenceUnitInfo pui = this.persistenceUnitInfos.remove(persistenceUnitName);
if (pui == null) {
if (!this.persistenceUnitInfoNames.contains(persistenceUnitName)) {
throw new IllegalArgumentException(
@@ -692,7 +691,7 @@ public class DefaultPersistenceUnitManager
"Persistence unit with name '" + persistenceUnitName + "' already obtained");
}
}
return pui;
return pui.toSmartPersistenceUnitInfo();
}
}
@@ -23,30 +23,31 @@ import java.util.Properties;
import javax.sql.DataSource;
import jakarta.persistence.PersistenceUnitTransactionType;
import jakarta.persistence.SharedCacheMode;
import jakarta.persistence.ValidationMode;
import jakarta.persistence.spi.ClassTransformer;
import jakarta.persistence.spi.PersistenceUnitTransactionType;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* Spring's base implementation of the JPA
* Spring's mutable equivalent of the JPA
* {@link jakarta.persistence.spi.PersistenceUnitInfo} interface,
* used to bootstrap an {@code EntityManagerFactory} in a container.
*
* <p>This implementation is largely a JavaBean, offering mutators
* for all standard {@code PersistenceUnitInfo} properties.
* As of 7.0, it does <i>not</i> implement {@code PersistenceUnitInfo} but
* rather serves as the state behind a runtime {@code PersistenceUnitInfo}
* (for achieving compatibility between JPA 3.2 and 4.0 and for preventing
* late mutation attempts through {@code PersistenceUnitInfo} downcasts).
*
* @author Rod Johnson
* @author Juergen Hoeller
* @author Costin Leau
* @since 2.0
*/
@SuppressWarnings("removal")
public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
public class MutablePersistenceUnitInfo {
private @Nullable String persistenceUnitName;
@@ -89,7 +90,6 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
this.persistenceUnitName = persistenceUnitName;
}
@Override
public @Nullable String getPersistenceUnitName() {
return this.persistenceUnitName;
}
@@ -98,7 +98,6 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
this.persistenceProviderClassName = persistenceProviderClassName;
}
@Override
public @Nullable String getPersistenceProviderClassName() {
return this.persistenceProviderClassName;
}
@@ -107,7 +106,6 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
this.scopeAnnotationName = scopeAnnotationName;
}
@Override
public @Nullable String getScopeAnnotationName() {
return this.scopeAnnotationName;
}
@@ -116,7 +114,6 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
this.qualifierAnnotationNames.add(qualifierAnnotationName);
}
@Override
public List<String> getQualifierAnnotationNames() {
return this.qualifierAnnotationNames;
}
@@ -125,7 +122,6 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
this.transactionType = transactionType;
}
@Override
public PersistenceUnitTransactionType getTransactionType() {
if (this.transactionType != null) {
return this.transactionType;
@@ -140,7 +136,6 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
this.jtaDataSource = jtaDataSource;
}
@Override
public @Nullable DataSource getJtaDataSource() {
return this.jtaDataSource;
}
@@ -149,7 +144,6 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
this.nonJtaDataSource = nonJtaDataSource;
}
@Override
public @Nullable DataSource getNonJtaDataSource() {
return this.nonJtaDataSource;
}
@@ -158,7 +152,6 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
this.mappingFileNames.add(mappingFileName);
}
@Override
public List<String> getMappingFileNames() {
return this.mappingFileNames;
}
@@ -167,7 +160,6 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
this.jarFileUrls.add(jarFileUrl);
}
@Override
public List<URL> getJarFileUrls() {
return this.jarFileUrls;
}
@@ -176,7 +168,6 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
this.persistenceUnitRootUrl = persistenceUnitRootUrl;
}
@Override
public @Nullable URL getPersistenceUnitRootUrl() {
return this.persistenceUnitRootUrl;
}
@@ -190,7 +181,6 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
this.managedClassNames.add(managedClassName);
}
@Override
public List<String> getManagedClassNames() {
return this.managedClassNames;
}
@@ -208,7 +198,6 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
this.managedPackages.add(packageName);
}
@Override
public List<String> getManagedPackages() {
return this.managedPackages;
}
@@ -217,7 +206,6 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
this.excludeUnlistedClasses = excludeUnlistedClasses;
}
@Override
public boolean excludeUnlistedClasses() {
return this.excludeUnlistedClasses;
}
@@ -226,7 +214,6 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
this.sharedCacheMode = sharedCacheMode;
}
@Override
public SharedCacheMode getSharedCacheMode() {
return this.sharedCacheMode;
}
@@ -235,7 +222,6 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
this.validationMode = validationMode;
}
@Override
public ValidationMode getValidationMode() {
return this.validationMode;
}
@@ -249,7 +235,6 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
this.properties = properties;
}
@Override
public Properties getProperties() {
return this.properties;
}
@@ -258,12 +243,10 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
this.persistenceXMLSchemaVersion = persistenceXMLSchemaVersion;
}
@Override
public String getPersistenceXMLSchemaVersion() {
return this.persistenceXMLSchemaVersion;
}
@Override
public void setPersistenceProviderPackageName(@Nullable String persistenceProviderPackageName) {
this.persistenceProviderPackageName = persistenceProviderPackageName;
}
@@ -273,32 +256,6 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
}
/**
* This implementation returns the default ClassLoader.
* @see org.springframework.util.ClassUtils#getDefaultClassLoader()
*/
@Override
public @Nullable ClassLoader getClassLoader() {
return ClassUtils.getDefaultClassLoader();
}
/**
* This implementation throws an UnsupportedOperationException.
*/
@Override
public void addTransformer(ClassTransformer classTransformer) {
throw new UnsupportedOperationException("addTransformer not supported");
}
/**
* This implementation throws an UnsupportedOperationException.
*/
@Override
public ClassLoader getNewTempClassLoader() {
throw new UnsupportedOperationException("getNewTempClassLoader not supported");
}
@Override
public String toString() {
return "PersistenceUnitInfo: name '" + this.persistenceUnitName +
@@ -17,9 +17,11 @@
package org.springframework.orm.jpa.persistenceunit;
/**
* Callback interface for post-processing a JPA PersistenceUnitInfo.
* Implementations can be registered with a DefaultPersistenceUnitManager
* or via a LocalContainerEntityManagerFactoryBean.
* Callback interface for post-processing a {@link MutablePersistenceUnitInfo}
* configuration that Spring prepares for JPA persistence unit bootstrapping.
*
* <p>Implementations can be registered with a {@link DefaultPersistenceUnitManager}
* or via a {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean}.
*
* @author Juergen Hoeller
* @since 2.0
@@ -29,10 +31,10 @@ package org.springframework.orm.jpa.persistenceunit;
public interface PersistenceUnitPostProcessor {
/**
* Post-process the given PersistenceUnitInfo, for example registering
* further entity classes and jar files.
* @param pui the chosen PersistenceUnitInfo, as read from {@code persistence.xml}.
* Passed in as MutablePersistenceUnitInfo.
* Post-process the given {@link MutablePersistenceUnitInfo},
* for example registering further entity classes and jar files.
* @param pui the chosen persistence unit configuration, as read from
* {@code persistence.xml}. Passed in as MutablePersistenceUnitInfo.
*/
void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui);
@@ -26,9 +26,9 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import jakarta.persistence.PersistenceUnitTransactionType;
import jakarta.persistence.SharedCacheMode;
import jakarta.persistence.ValidationMode;
import jakarta.persistence.spi.PersistenceUnitTransactionType;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
@@ -189,7 +189,6 @@ final class PersistenceUnitReader {
/**
* Parse the unit info DOM element.
*/
@SuppressWarnings("removal")
SpringPersistenceUnitInfo parsePersistenceUnitInfo(
Element persistenceUnit, String version, @Nullable URL rootUrl) throws IOException {
@@ -47,4 +47,13 @@ public interface SmartPersistenceUnitInfo extends PersistenceUnitInfo {
*/
void setPersistenceProviderPackageName(String persistenceProviderPackageName);
/**
* Determine whether this persistence unit is configured for JTA transactions.
* <p>This allows for a quick check without referring to the JPA transaction type enum
* (primarily for achieving compatibility between JPA 3.2 and 4.0).
* @since 7.0
* @see jakarta.persistence.PersistenceUnitTransactionType#JTA
*/
boolean isConfiguredForJta();
}
@@ -16,6 +16,11 @@
package org.springframework.orm.jpa.persistenceunit;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import jakarta.persistence.PersistenceUnitTransactionType;
import jakarta.persistence.spi.ClassTransformer;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
@@ -24,6 +29,7 @@ import org.springframework.core.DecoratingClassLoader;
import org.springframework.instrument.classloading.LoadTimeWeaver;
import org.springframework.instrument.classloading.SimpleThrowawayClassLoader;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
* Subclass of {@link MutablePersistenceUnitInfo} that adds instrumentation hooks based on
@@ -67,7 +73,6 @@ class SpringPersistenceUnitInfo extends MutablePersistenceUnitInfo {
* This implementation returns the LoadTimeWeaver's instrumentable ClassLoader,
* if specified.
*/
@Override
public @Nullable ClassLoader getClassLoader() {
return this.classLoader;
}
@@ -75,7 +80,6 @@ class SpringPersistenceUnitInfo extends MutablePersistenceUnitInfo {
/**
* This implementation delegates to the LoadTimeWeaver, if specified.
*/
@Override
public void addTransformer(ClassTransformer classTransformer) {
if (this.loadTimeWeaver != null) {
this.loadTimeWeaver.addTransformer(new ClassFileTransformerAdapter(classTransformer));
@@ -88,7 +92,6 @@ class SpringPersistenceUnitInfo extends MutablePersistenceUnitInfo {
/**
* This implementation delegates to the LoadTimeWeaver, if specified.
*/
@Override
public ClassLoader getNewTempClassLoader() {
ClassLoader tcl = (this.loadTimeWeaver != null ? this.loadTimeWeaver.getThrowawayClassLoader() :
new SimpleThrowawayClassLoader(this.classLoader));
@@ -99,4 +102,42 @@ class SpringPersistenceUnitInfo extends MutablePersistenceUnitInfo {
return tcl;
}
/**
* Expose a {@link SmartPersistenceUnitInfo} proxy for the persistence unit
* configuration in this {@link MutablePersistenceUnitInfo} instance.
* @since 7.0
*/
public SmartPersistenceUnitInfo toSmartPersistenceUnitInfo() {
return (SmartPersistenceUnitInfo) Proxy.newProxyInstance(getClass().getClassLoader(),
new Class<?>[] {SmartPersistenceUnitInfo.class},
new JpaPersistenceUnitInfoInvocationHandler());
}
private class JpaPersistenceUnitInfoInvocationHandler implements InvocationHandler {
@SuppressWarnings("unchecked")
@Override
public @Nullable Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Fast path for SmartPersistenceUnitInfo JTA check
if (method.getName().equals("isConfiguredForJta")) {
return (getTransactionType() == PersistenceUnitTransactionType.JTA);
}
// Regular methods to be delegated to SpringPersistenceUnitInfo
Method targetMethod = SpringPersistenceUnitInfo.class.getMethod(method.getName(), method.getParameterTypes());
ReflectionUtils.makeAccessible(targetMethod);
Object returnValue = ReflectionUtils.invokeMethod(targetMethod, SpringPersistenceUnitInfo.this, args);
// Special handling for JPA 3.2 vs 4.0 getTransactionType() return type
Class<?> returnType = method.getReturnType();
if (returnType.isEnum() && returnValue != null && !returnType.isInstance(returnValue)) {
return Enum.valueOf((Class<Enum>) returnType, returnValue.toString());
}
return returnValue;
}
}
}
@@ -23,7 +23,6 @@ import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.spi.PersistenceProvider;
import jakarta.persistence.spi.PersistenceUnitInfo;
import jakarta.persistence.spi.PersistenceUnitTransactionType;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AvailableSettings;
@@ -39,6 +38,8 @@ import org.hibernate.dialect.SybaseDialect;
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
import org.jspecify.annotations.Nullable;
import org.springframework.orm.jpa.persistenceunit.SmartPersistenceUnitInfo;
/**
* {@link org.springframework.orm.jpa.JpaVendorAdapter} implementation for Hibernate.
* Compatible with Hibernate ORM 7.x.
@@ -120,11 +121,10 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
return "org.hibernate";
}
@SuppressWarnings("removal")
@Override
public Map<String, Object> getJpaPropertyMap(PersistenceUnitInfo pui) {
return buildJpaPropertyMap(this.jpaDialect.prepareConnection &&
pui.getTransactionType() != PersistenceUnitTransactionType.JTA);
(pui instanceof SmartPersistenceUnitInfo spui && !spui.isConfiguredForJta()));
}
@Override
@@ -25,9 +25,9 @@ import jakarta.persistence.EntityTransaction;
import jakarta.persistence.OptimisticLockException;
import jakarta.persistence.PersistenceConfiguration;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.PersistenceUnitTransactionType;
import jakarta.persistence.spi.PersistenceProvider;
import jakarta.persistence.spi.PersistenceUnitInfo;
import jakarta.persistence.spi.PersistenceUnitTransactionType;
import jakarta.persistence.spi.ProviderUtil;
import org.junit.jupiter.api.Test;
@@ -36,7 +36,7 @@ import org.springframework.core.testfixture.io.SerializationTestUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver;
import org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo;
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
@@ -215,9 +215,8 @@ class LocalContainerEntityManagerFactoryBeanTests extends AbstractEntityManagerF
given(mockEmf.createEntityManager()).willReturn(sharedEm, mockEm);
LocalContainerEntityManagerFactoryBean cefb = parseValidPersistenceUnit();
MutablePersistenceUnitInfo pui = ((MutablePersistenceUnitInfo) cefb.getPersistenceUnitInfo());
pui.setTransactionType(PersistenceUnitTransactionType.JTA);
LocalContainerEntityManagerFactoryBean cefb = parseValidPersistenceUnit(
pui -> pui.setTransactionType(PersistenceUnitTransactionType.JTA));
JpaTransactionManager jpatm = new JpaTransactionManager();
jpatm.setEntityManagerFactory(cefb.getObject());
@@ -241,10 +240,12 @@ class LocalContainerEntityManagerFactoryBeanTests extends AbstractEntityManagerF
verify(mockEmf).close();
}
public LocalContainerEntityManagerFactoryBean parseValidPersistenceUnit() throws Exception {
public LocalContainerEntityManagerFactoryBean parseValidPersistenceUnit(
PersistenceUnitPostProcessor... postProcessors) {
return createEntityManagerFactoryBean(
"org/springframework/orm/jpa/domain/persistence.xml", null,
"Person");
"Person", postProcessors);
}
@Test
@@ -255,7 +256,8 @@ class LocalContainerEntityManagerFactoryBeanTests extends AbstractEntityManagerF
@SuppressWarnings("unchecked")
protected LocalContainerEntityManagerFactoryBean createEntityManagerFactoryBean(
String persistenceXml, Properties props, String entityManagerName) {
String persistenceXml, Properties props, String entityManagerName,
PersistenceUnitPostProcessor... postProcessors) {
// This will be set by DummyPersistenceProvider
actualPui = null;
@@ -270,6 +272,7 @@ class LocalContainerEntityManagerFactoryBeanTests extends AbstractEntityManagerF
}
containerEmfb.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
containerEmfb.setPersistenceXmlLocation(persistenceXml);
containerEmfb.setPersistenceUnitPostProcessors(postProcessors);
containerEmfb.afterPropertiesSet();
assertThat(actualPui.getPersistenceUnitName()).isEqualTo(entityManagerName);
@@ -16,6 +16,7 @@
package org.springframework.orm.jpa.persistenceunit;
import jakarta.persistence.spi.PersistenceUnitInfo;
import org.junit.jupiter.api.Test;
import org.springframework.context.testfixture.index.CandidateComponentsTestClassLoader;
@@ -25,17 +26,17 @@ import org.springframework.orm.jpa.domain.Person;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link DefaultPersistenceUnitManager}.
*
* @author Stephane Nicoll
* @author Juergen Hoeller
*/
class DefaultPersistenceUnitManagerTests {
private final DefaultPersistenceUnitManager manager = new DefaultPersistenceUnitManager();
@Test
void defaultDomainWithScan() {
this.manager.setPackagesToScan("org.springframework.orm.jpa.domain");
@@ -54,15 +55,11 @@ class DefaultPersistenceUnitManagerTests {
}
private void testDefaultDomain() {
SpringPersistenceUnitInfo puInfo = buildDefaultPersistenceUnitInfo();
assertThat(puInfo.getManagedClassNames()).contains(
this.manager.preparePersistenceUnitInfos();
PersistenceUnitInfo pui = this.manager.obtainDefaultPersistenceUnitInfo();
assertThat(pui.getManagedClassNames()).contains(
"org.springframework.orm.jpa.domain.Person",
"org.springframework.orm.jpa.domain.DriversLicense");
}
private SpringPersistenceUnitInfo buildDefaultPersistenceUnitInfo() {
this.manager.preparePersistenceUnitInfos();
return (SpringPersistenceUnitInfo) this.manager.obtainDefaultPersistenceUnitInfo();
}
}
@@ -22,8 +22,7 @@ import java.util.Map;
import javax.sql.DataSource;
import jakarta.persistence.spi.PersistenceUnitInfo;
import jakarta.persistence.spi.PersistenceUnitTransactionType;
import jakarta.persistence.PersistenceUnitTransactionType;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@@ -55,7 +54,7 @@ class PersistenceXmlParsingTests {
PersistenceUnitReader reader = new PersistenceUnitReader(
new PathMatchingResourcePatternResolver(), new JndiDataSourceLookup());
String resource = "/org/springframework/orm/jpa/META-INF/persistence.xml";
PersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
SpringPersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
assertThat(info).isNotNull();
assertThat(info).hasSize(1);
@@ -72,7 +71,7 @@ class PersistenceXmlParsingTests {
PersistenceUnitReader reader = new PersistenceUnitReader(
new PathMatchingResourcePatternResolver(), new JndiDataSourceLookup());
String resource = "/org/springframework/orm/jpa/persistence-example1.xml";
PersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
SpringPersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
assertThat(info).isNotNull();
assertThat(info).hasSize(1);
@@ -86,7 +85,7 @@ class PersistenceXmlParsingTests {
PersistenceUnitReader reader = new PersistenceUnitReader(
new PathMatchingResourcePatternResolver(), new JndiDataSourceLookup());
String resource = "/org/springframework/orm/jpa/persistence-example2.xml";
PersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
SpringPersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
assertThat(info).isNotNull();
assertThat(info).hasSize(1);
@@ -104,7 +103,7 @@ class PersistenceXmlParsingTests {
PersistenceUnitReader reader = new PersistenceUnitReader(
new PathMatchingResourcePatternResolver(), new JndiDataSourceLookup());
String resource = "/org/springframework/orm/jpa/persistence-example3.xml";
PersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
SpringPersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
assertThat(info).isNotNull();
assertThat(info).hasSize(1);
@@ -130,7 +129,7 @@ class PersistenceXmlParsingTests {
PersistenceUnitReader reader = new PersistenceUnitReader(
new PathMatchingResourcePatternResolver(), new JndiDataSourceLookup());
String resource = "/org/springframework/orm/jpa/persistence-example4.xml";
PersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
SpringPersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
assertThat(info).isNotNull();
assertThat(info).hasSize(1);
@@ -154,7 +153,7 @@ class PersistenceXmlParsingTests {
PersistenceUnitReader reader = new PersistenceUnitReader(
new PathMatchingResourcePatternResolver(), new JndiDataSourceLookup());
String resource = "/org/springframework/orm/jpa/persistence-example5.xml";
PersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
SpringPersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
assertThat(info).isNotNull();
assertThat(info).hasSize(1);
@@ -184,11 +183,11 @@ class PersistenceXmlParsingTests {
dataSourceLookup.setDataSources(dataSources);
PersistenceUnitReader reader = new PersistenceUnitReader(
new PathMatchingResourcePatternResolver(), dataSourceLookup);
PersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
SpringPersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
assertThat(info).hasSize(2);
PersistenceUnitInfo pu1 = info[0];
SpringPersistenceUnitInfo pu1 = info[0];
assertThat(pu1.getPersistenceUnitName()).isEqualTo("pu1");
@@ -211,7 +210,7 @@ class PersistenceXmlParsingTests {
assertThat(pu1.excludeUnlistedClasses()).as("Exclude unlisted should default false in 1.0.").isFalse();
PersistenceUnitInfo pu2 = info[1];
SpringPersistenceUnitInfo pu2 = info[1];
assertThat(pu2.getTransactionType()).isSameAs(PersistenceUnitTransactionType.JTA);
assertThat(pu2.getPersistenceProviderClassName()).isEqualTo("com.acme.AcmePersistence");
@@ -235,7 +234,7 @@ class PersistenceXmlParsingTests {
PersistenceUnitReader reader = new PersistenceUnitReader(
new PathMatchingResourcePatternResolver(), new JndiDataSourceLookup());
String resource = "/org/springframework/orm/jpa/persistence-example6.xml";
PersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
SpringPersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
assertThat(info).hasSize(1);
assertThat(info[0].getPersistenceUnitName()).isEqualTo("pu");
assertThat(info[0].getProperties()).isEmpty();
@@ -287,27 +286,27 @@ class PersistenceXmlParsingTests {
PersistenceUnitReader reader = new PersistenceUnitReader(
new PathMatchingResourcePatternResolver(), new JndiDataSourceLookup());
String resource = "/org/springframework/orm/jpa/persistence-exclude-1.0.xml";
PersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
SpringPersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
assertThat(info).isNotNull();
assertThat(info.length).as("The number of persistence units is incorrect.").isEqualTo(4);
PersistenceUnitInfo noExclude = info[0];
SpringPersistenceUnitInfo noExclude = info[0];
assertThat(noExclude).as("noExclude should not be null.").isNotNull();
assertThat(noExclude.getPersistenceUnitName()).as("noExclude name is not correct.").isEqualTo("NoExcludeElement");
assertThat(noExclude.excludeUnlistedClasses()).as("Exclude unlisted should default false in 1.0.").isFalse();
PersistenceUnitInfo emptyExclude = info[1];
SpringPersistenceUnitInfo emptyExclude = info[1];
assertThat(emptyExclude).as("emptyExclude should not be null.").isNotNull();
assertThat(emptyExclude.getPersistenceUnitName()).as("emptyExclude name is not correct.").isEqualTo("EmptyExcludeElement");
assertThat(emptyExclude.excludeUnlistedClasses()).as("emptyExclude should be true.").isTrue();
PersistenceUnitInfo trueExclude = info[2];
SpringPersistenceUnitInfo trueExclude = info[2];
assertThat(trueExclude).as("trueExclude should not be null.").isNotNull();
assertThat(trueExclude.getPersistenceUnitName()).as("trueExclude name is not correct.").isEqualTo("TrueExcludeElement");
assertThat(trueExclude.excludeUnlistedClasses()).as("trueExclude should be true.").isTrue();
PersistenceUnitInfo falseExclude = info[3];
SpringPersistenceUnitInfo falseExclude = info[3];
assertThat(falseExclude).as("falseExclude should not be null.").isNotNull();
assertThat(falseExclude.getPersistenceUnitName()).as("falseExclude name is not correct.").isEqualTo("FalseExcludeElement");
assertThat(falseExclude.excludeUnlistedClasses()).as("falseExclude should be false.").isFalse();
@@ -318,27 +317,27 @@ class PersistenceXmlParsingTests {
PersistenceUnitReader reader = new PersistenceUnitReader(
new PathMatchingResourcePatternResolver(), new JndiDataSourceLookup());
String resource = "/org/springframework/orm/jpa/persistence-exclude-2.0.xml";
PersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
SpringPersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
assertThat(info).isNotNull();
assertThat(info.length).as("The number of persistence units is incorrect.").isEqualTo(4);
PersistenceUnitInfo noExclude = info[0];
SpringPersistenceUnitInfo noExclude = info[0];
assertThat(noExclude).as("noExclude should not be null.").isNotNull();
assertThat(noExclude.getPersistenceUnitName()).as("noExclude name is not correct.").isEqualTo("NoExcludeElement");
assertThat(noExclude.excludeUnlistedClasses()).as("Exclude unlisted still defaults to false in 2.0.").isFalse();
PersistenceUnitInfo emptyExclude = info[1];
SpringPersistenceUnitInfo emptyExclude = info[1];
assertThat(emptyExclude).as("emptyExclude should not be null.").isNotNull();
assertThat(emptyExclude.getPersistenceUnitName()).as("emptyExclude name is not correct.").isEqualTo("EmptyExcludeElement");
assertThat(emptyExclude.excludeUnlistedClasses()).as("emptyExclude should be true.").isTrue();
PersistenceUnitInfo trueExclude = info[2];
SpringPersistenceUnitInfo trueExclude = info[2];
assertThat(trueExclude).as("trueExclude should not be null.").isNotNull();
assertThat(trueExclude.getPersistenceUnitName()).as("trueExclude name is not correct.").isEqualTo("TrueExcludeElement");
assertThat(trueExclude.excludeUnlistedClasses()).as("trueExclude should be true.").isTrue();
PersistenceUnitInfo falseExclude = info[3];
SpringPersistenceUnitInfo falseExclude = info[3];
assertThat(falseExclude).as("falseExclude should not be null.").isNotNull();
assertThat(falseExclude.getPersistenceUnitName()).as("falseExclude name is not correct.").isEqualTo("FalseExcludeElement");
assertThat(falseExclude.excludeUnlistedClasses()).as("falseExclude should be false.").isFalse();