mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-17 08:24:13 +00:00
Add support for JPA 3.2 PersistenceConfiguration
See gh-35662
This commit is contained in:
+3
-1
@@ -71,7 +71,9 @@ import org.springframework.util.CollectionUtils;
|
||||
* making {@code EntityManager} available for dependency injection as well.
|
||||
*
|
||||
* <p>Encapsulates the common functionality between the different JPA bootstrap
|
||||
* contracts (standalone as well as container).
|
||||
* contracts: standalone as well as container. Note that as of 7.0, the JPA 3.2
|
||||
* {@link LocalEntityManagerFactoryBean#setPersistenceConfiguration PersistenceConfiguration}
|
||||
* mechanism is supported as well, allowing for much richer standalone bootstrap options.
|
||||
*
|
||||
* <p>Implements support for standard JPA configuration conventions as well as
|
||||
* Spring's customizable {@link JpaVendorAdapter} mechanism, and controls the
|
||||
|
||||
+23
-5
@@ -21,6 +21,7 @@ import java.util.List;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
import jakarta.persistence.PersistenceConfiguration;
|
||||
import jakarta.persistence.PersistenceException;
|
||||
import jakarta.persistence.SharedCacheMode;
|
||||
import jakarta.persistence.ValidationMode;
|
||||
@@ -166,6 +167,22 @@ public class LocalContainerEntityManagerFactoryBean extends AbstractEntityManage
|
||||
this.internalPersistenceUnitManager.setDefaultPersistenceUnitRootLocation(defaultPersistenceUnitRootLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a local JPA 3.2 {@link PersistenceConfiguration} to use for this
|
||||
* persistence unit.
|
||||
* <p>Note: {@link PersistenceConfiguration} includes a persistence unit name,
|
||||
* so this effectively overrides the {@link #setPersistenceUnitName} method.
|
||||
* In contrast, all other settings will be merged with the settings in the
|
||||
* {@code PersistenceConfiguration} instance.
|
||||
* @since 7.0
|
||||
* @see DefaultPersistenceUnitManager#setPersistenceConfiguration
|
||||
*/
|
||||
public void setPersistenceConfiguration(PersistenceConfiguration configuration) {
|
||||
Assert.notNull(configuration, "PersistenceConfiguration must not be null");
|
||||
super.setPersistenceUnitName(configuration.name());
|
||||
this.internalPersistenceUnitManager.setPersistenceConfiguration(configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link PersistenceManagedTypes} to use to build the list of managed types
|
||||
* as an alternative to entity scanning.
|
||||
@@ -424,15 +441,16 @@ public class LocalContainerEntityManagerFactoryBean extends AbstractEntityManage
|
||||
* Determine the PersistenceUnitInfo to use for the EntityManagerFactory
|
||||
* created by this bean.
|
||||
* <p>The default implementation reads in all persistence unit infos from
|
||||
* {@code persistence.xml}, as defined in the JPA specification.
|
||||
* If no entity manager name was specified, it takes the first info in the
|
||||
* array as returned by the reader. Otherwise, it checks for a matching name.
|
||||
* {@code persistence.xml}, as defined in the JPA specification, selecting a unit
|
||||
* by name. If no persistence unit name was specified, it takes the default one
|
||||
* if configured, or otherwise the first persistence unit as found by the reader.
|
||||
* @param persistenceUnitManager the PersistenceUnitManager to obtain from
|
||||
* @return the chosen PersistenceUnitInfo
|
||||
*/
|
||||
protected PersistenceUnitInfo determinePersistenceUnitInfo(PersistenceUnitManager persistenceUnitManager) {
|
||||
if (getPersistenceUnitName() != null) {
|
||||
return persistenceUnitManager.obtainPersistenceUnitInfo(getPersistenceUnitName());
|
||||
String persistenceUnitName = getPersistenceUnitName();
|
||||
if (persistenceUnitName != null) {
|
||||
return persistenceUnitManager.obtainPersistenceUnitInfo(persistenceUnitName);
|
||||
}
|
||||
else {
|
||||
return persistenceUnitManager.obtainDefaultPersistenceUnitInfo();
|
||||
|
||||
+89
-2
@@ -20,10 +20,14 @@ import javax.sql.DataSource;
|
||||
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
import jakarta.persistence.Persistence;
|
||||
import jakarta.persistence.PersistenceConfiguration;
|
||||
import jakarta.persistence.PersistenceException;
|
||||
import jakarta.persistence.spi.PersistenceProvider;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.FactoryBean} that creates a JPA
|
||||
* {@link jakarta.persistence.EntityManagerFactory} according to JPA's standard
|
||||
@@ -62,6 +66,80 @@ public class LocalEntityManagerFactoryBean extends AbstractEntityManagerFactoryB
|
||||
|
||||
private static final String DATASOURCE_PROPERTY = "jakarta.persistence.dataSource";
|
||||
|
||||
private @Nullable PersistenceConfiguration configuration;
|
||||
|
||||
|
||||
/**
|
||||
* Create a {@code LocalEntityManagerFactoryBean}.
|
||||
* <p>As of 7.0, This uses "default" for the default persistence unit name.
|
||||
* @see #setPersistenceUnitName
|
||||
* @see #setPersistenceConfiguration
|
||||
*/
|
||||
public LocalEntityManagerFactoryBean() {
|
||||
setPersistenceUnitName(DefaultPersistenceUnitManager.ORIGINAL_DEFAULT_PERSISTENCE_UNIT_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@code LocalEntityManagerFactoryBean} for the given persistence unit.
|
||||
* @param persistenceUnitName the name of the persistence unit
|
||||
* @since 7.0
|
||||
*/
|
||||
public LocalEntityManagerFactoryBean(String persistenceUnitName) {
|
||||
setPersistenceUnitName(persistenceUnitName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@code LocalEntityManagerFactoryBean} for the given persistence unit.
|
||||
* @param configuration the configuration for the persistence unit
|
||||
* @since 7.0
|
||||
*/
|
||||
public LocalEntityManagerFactoryBean(PersistenceConfiguration configuration) {
|
||||
setPersistenceConfiguration(configuration);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a local JPA 3.2 {@link PersistenceConfiguration} to use for creating
|
||||
* the EntityManagerFactory. This can be a provider-specific subclass such as
|
||||
* {@link org.hibernate.jpa.HibernatePersistenceConfiguration}, exposing a
|
||||
* complete programmatic persistence unit configuration which replaces
|
||||
* {@code persistence.xml} (including provider-specific classpath scanning).
|
||||
* <p>Note: {@link PersistenceConfiguration} includes a persistence unit name,
|
||||
* so this effectively overrides the {@link #setPersistenceUnitName} method.
|
||||
* In contrast, locally specified JPA properties ({@link #setJpaProperties})
|
||||
* will get merged into the given {@code PersistenceConfiguration} instance.
|
||||
* @since 7.0
|
||||
* @see #getPersistenceConfiguration()
|
||||
* @see #getPersistenceUnitName()
|
||||
*/
|
||||
public void setPersistenceConfiguration(PersistenceConfiguration configuration) {
|
||||
Assert.notNull(configuration, "PersistenceConfiguration must not be null");
|
||||
this.configuration = configuration;
|
||||
setPersistenceUnitName(configuration.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a local JPA 3.2 {@link PersistenceConfiguration} to use for creating
|
||||
* the EntityManagerFactory. If none is in use yet, a new plain
|
||||
* {@link PersistenceConfiguration} for the configured persistence unit name
|
||||
* will be created and returned.
|
||||
* @since 7.0
|
||||
* @see #setPersistenceConfiguration
|
||||
* @see #setPersistenceUnitName
|
||||
*/
|
||||
public PersistenceConfiguration getPersistenceConfiguration() {
|
||||
if (this.configuration == null) {
|
||||
this.configuration = new PersistenceConfiguration(getPersistenceUnitName());
|
||||
}
|
||||
return this.configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPersistenceUnitName(@Nullable String persistenceUnitName) {
|
||||
Assert.state(this.configuration == null || this.configuration.name().equals(persistenceUnitName),
|
||||
"Cannot change setPersistenceUnitName when PersistenceConfiguration has been set");
|
||||
super.setPersistenceUnitName(persistenceUnitName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the JDBC DataSource that the JPA persistence provider is supposed
|
||||
@@ -104,10 +182,17 @@ public class LocalEntityManagerFactoryBean extends AbstractEntityManagerFactoryB
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Building JPA EntityManagerFactory for persistence unit '" + getPersistenceUnitName() + "'");
|
||||
}
|
||||
|
||||
if (this.configuration != null) {
|
||||
this.configuration.properties(getJpaPropertyMap());
|
||||
}
|
||||
|
||||
PersistenceProvider provider = getPersistenceProvider();
|
||||
if (provider != null) {
|
||||
// Create EntityManagerFactory directly through PersistenceProvider.
|
||||
EntityManagerFactory emf = provider.createEntityManagerFactory(getPersistenceUnitName(), getJpaPropertyMap());
|
||||
EntityManagerFactory emf = (this.configuration != null ?
|
||||
provider.createEntityManagerFactory(this.configuration) :
|
||||
provider.createEntityManagerFactory(getPersistenceUnitName(), getJpaPropertyMap()));
|
||||
if (emf == null) {
|
||||
throw new IllegalStateException(
|
||||
"PersistenceProvider [" + provider + "] did not return an EntityManagerFactory for name '" +
|
||||
@@ -117,7 +202,9 @@ public class LocalEntityManagerFactoryBean extends AbstractEntityManagerFactoryB
|
||||
}
|
||||
else {
|
||||
// Let JPA perform its standard PersistenceProvider autodetection.
|
||||
return Persistence.createEntityManagerFactory(getPersistenceUnitName(), getJpaPropertyMap());
|
||||
return (this.configuration != null ?
|
||||
Persistence.createEntityManagerFactory(this.configuration) :
|
||||
Persistence.createEntityManagerFactory(getPersistenceUnitName(), getJpaPropertyMap()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+33
-23
@@ -27,6 +27,7 @@ import java.util.Set;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import jakarta.persistence.PersistenceConfiguration;
|
||||
import jakarta.persistence.PersistenceException;
|
||||
import jakarta.persistence.SharedCacheMode;
|
||||
import jakarta.persistence.ValidationMode;
|
||||
@@ -108,6 +109,8 @@ public class DefaultPersistenceUnitManager
|
||||
|
||||
private @Nullable String defaultPersistenceUnitName = ORIGINAL_DEFAULT_PERSISTENCE_UNIT_NAME;
|
||||
|
||||
private @Nullable PersistenceConfiguration persistenceConfiguration;
|
||||
|
||||
private @Nullable PersistenceManagedTypes managedTypes;
|
||||
|
||||
private String @Nullable [] packagesToScan;
|
||||
@@ -179,9 +182,19 @@ public class DefaultPersistenceUnitManager
|
||||
this.defaultPersistenceUnitName = defaultPersistenceUnitName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a JPA 3.2 {@link PersistenceConfiguration} to apply to the default
|
||||
* persistence unit. The contained configuration will be merged with the
|
||||
* common settings specified on this {@code DefaultPersistenceUnitManager}.
|
||||
* @since 7.0
|
||||
*/
|
||||
public void setPersistenceConfiguration(PersistenceConfiguration configuration) {
|
||||
this.persistenceConfiguration = configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link PersistenceManagedTypes} to use to build the list of managed types
|
||||
* as an alternative to entity scanning.
|
||||
* for the default persistence unit, as an alternative to entity scanning.
|
||||
* @param managedTypes the managed types
|
||||
* @since 6.0
|
||||
*/
|
||||
@@ -492,7 +505,8 @@ public class DefaultPersistenceUnitManager
|
||||
private List<SpringPersistenceUnitInfo> readPersistenceUnitInfos() {
|
||||
List<SpringPersistenceUnitInfo> infos = new ArrayList<>(1);
|
||||
String defaultName = this.defaultPersistenceUnitName;
|
||||
boolean buildDefaultUnit = (this.managedTypes != null || this.packagesToScan != null || this.mappingResources != null);
|
||||
boolean buildDefaultUnit = (this.persistenceConfiguration != null || this.managedTypes != null ||
|
||||
this.packagesToScan != null || this.mappingResources != null);
|
||||
boolean foundDefaultUnit = false;
|
||||
|
||||
PersistenceUnitReader reader = new PersistenceUnitReader(this.resourcePatternResolver, this.dataSourceLookup);
|
||||
@@ -507,8 +521,9 @@ public class DefaultPersistenceUnitManager
|
||||
if (buildDefaultUnit) {
|
||||
if (foundDefaultUnit) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Found explicit default persistence unit with name '" + defaultName + "' in persistence.xml - " +
|
||||
"overriding local default persistence unit settings ('managedTypes', 'packagesToScan' or 'mappingResources')");
|
||||
logger.warn("Found explicit default persistence unit with name '" + defaultName +
|
||||
"' in persistence.xml - overriding local default persistence unit settings " +
|
||||
"(`persistenceConfiguration`, 'managedTypes', 'packagesToScan' or 'mappingResources')");
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -523,33 +538,37 @@ public class DefaultPersistenceUnitManager
|
||||
* @see #setPackagesToScan
|
||||
*/
|
||||
private SpringPersistenceUnitInfo buildDefaultPersistenceUnitInfo() {
|
||||
SpringPersistenceUnitInfo scannedUnit = new SpringPersistenceUnitInfo();
|
||||
SpringPersistenceUnitInfo defaultUnit = new SpringPersistenceUnitInfo();
|
||||
if (this.defaultPersistenceUnitName != null) {
|
||||
scannedUnit.setPersistenceUnitName(this.defaultPersistenceUnitName);
|
||||
defaultUnit.setPersistenceUnitName(this.defaultPersistenceUnitName);
|
||||
}
|
||||
defaultUnit.setExcludeUnlistedClasses(true);
|
||||
|
||||
if (this.persistenceConfiguration != null) {
|
||||
defaultUnit.apply(this.persistenceConfiguration, this.dataSourceLookup);
|
||||
}
|
||||
scannedUnit.setExcludeUnlistedClasses(true);
|
||||
|
||||
if (this.managedTypes != null) {
|
||||
applyManagedTypes(scannedUnit, this.managedTypes);
|
||||
defaultUnit.apply(this.managedTypes);
|
||||
}
|
||||
else if (this.packagesToScan != null) {
|
||||
PersistenceManagedTypesScanner scanner = new PersistenceManagedTypesScanner(
|
||||
this.resourcePatternResolver, this.managedClassNameFilter);
|
||||
applyManagedTypes(scannedUnit, scanner.scan(this.packagesToScan));
|
||||
defaultUnit.apply(scanner.scan(this.packagesToScan));
|
||||
}
|
||||
|
||||
if (this.mappingResources != null) {
|
||||
for (String mappingFileName : this.mappingResources) {
|
||||
scannedUnit.addMappingFileName(mappingFileName);
|
||||
defaultUnit.addMappingFileName(mappingFileName);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Resource ormXml = getOrmXmlForDefaultPersistenceUnit();
|
||||
if (ormXml != null) {
|
||||
scannedUnit.addMappingFileName(DEFAULT_ORM_XML_RESOURCE);
|
||||
if (scannedUnit.getPersistenceUnitRootUrl() == null) {
|
||||
defaultUnit.addMappingFileName(DEFAULT_ORM_XML_RESOURCE);
|
||||
if (defaultUnit.getPersistenceUnitRootUrl() == null) {
|
||||
try {
|
||||
scannedUnit.setPersistenceUnitRootUrl(
|
||||
defaultUnit.setPersistenceUnitRootUrl(
|
||||
PersistenceUnitReader.determinePersistenceUnitRootUrl(ormXml));
|
||||
}
|
||||
catch (IOException ex) {
|
||||
@@ -559,16 +578,7 @@ public class DefaultPersistenceUnitManager
|
||||
}
|
||||
}
|
||||
|
||||
return scannedUnit;
|
||||
}
|
||||
|
||||
private void applyManagedTypes(SpringPersistenceUnitInfo scannedUnit, PersistenceManagedTypes managedTypes) {
|
||||
managedTypes.getManagedClassNames().forEach(scannedUnit::addManagedClassName);
|
||||
managedTypes.getManagedPackages().forEach(scannedUnit::addManagedPackage);
|
||||
URL persistenceUnitRootUrl = managedTypes.getPersistenceUnitRootUrl();
|
||||
if (scannedUnit.getPersistenceUnitRootUrl() == null && persistenceUnitRootUrl != null) {
|
||||
scannedUnit.setPersistenceUnitRootUrl(persistenceUnitRootUrl);
|
||||
}
|
||||
return defaultUnit;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-22
@@ -60,16 +60,12 @@ public class MutablePersistenceUnitInfo {
|
||||
|
||||
private @Nullable String persistenceProviderClassName;
|
||||
|
||||
private @Nullable String scopeAnnotationName;
|
||||
|
||||
private final List<String> qualifierAnnotationNames = new ArrayList<>();
|
||||
|
||||
private @Nullable PersistenceUnitTransactionType transactionType;
|
||||
|
||||
private @Nullable DataSource nonJtaDataSource;
|
||||
|
||||
private @Nullable DataSource jtaDataSource;
|
||||
|
||||
private @Nullable DataSource nonJtaDataSource;
|
||||
|
||||
private final List<String> mappingFileNames = new ArrayList<>();
|
||||
|
||||
private final List<URL> jarFileUrls = new ArrayList<>();
|
||||
@@ -109,22 +105,6 @@ public class MutablePersistenceUnitInfo {
|
||||
return this.persistenceProviderClassName;
|
||||
}
|
||||
|
||||
public void setScopeAnnotationName(@Nullable String scopeAnnotationName) {
|
||||
this.scopeAnnotationName = scopeAnnotationName;
|
||||
}
|
||||
|
||||
public @Nullable String getScopeAnnotationName() {
|
||||
return this.scopeAnnotationName;
|
||||
}
|
||||
|
||||
public void addQualifierAnnotationName(String qualifierAnnotationName) {
|
||||
this.qualifierAnnotationNames.add(qualifierAnnotationName);
|
||||
}
|
||||
|
||||
public List<String> getQualifierAnnotationNames() {
|
||||
return this.qualifierAnnotationNames;
|
||||
}
|
||||
|
||||
public void setTransactionType(PersistenceUnitTransactionType transactionType) {
|
||||
this.transactionType = transactionType;
|
||||
}
|
||||
|
||||
+92
-1
@@ -19,7 +19,11 @@ package org.springframework.orm.jpa.persistenceunit;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.persistence.PersistenceConfiguration;
|
||||
import jakarta.persistence.PersistenceUnitTransactionType;
|
||||
import jakarta.persistence.spi.ClassTransformer;
|
||||
import jakarta.persistence.spi.PersistenceUnitInfo;
|
||||
@@ -29,7 +33,9 @@ import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.core.DecoratingClassLoader;
|
||||
import org.springframework.instrument.classloading.LoadTimeWeaver;
|
||||
import org.springframework.instrument.classloading.SimpleThrowawayClassLoader;
|
||||
import org.springframework.jdbc.datasource.lookup.DataSourceLookup;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
@@ -55,6 +61,10 @@ public class SpringPersistenceUnitInfo extends MutablePersistenceUnitInfo {
|
||||
|
||||
private @Nullable ClassLoader classLoader;
|
||||
|
||||
private @Nullable String scopeAnnotationName;
|
||||
|
||||
private final List<String> qualifierAnnotationNames = new ArrayList<>();
|
||||
|
||||
|
||||
/**
|
||||
* Construct a new SpringPersistenceUnitInfo for custom purposes.
|
||||
@@ -132,6 +142,87 @@ public class SpringPersistenceUnitInfo extends MutablePersistenceUnitInfo {
|
||||
return tcl;
|
||||
}
|
||||
|
||||
public void setScopeAnnotationName(@Nullable String scopeAnnotationName) {
|
||||
this.scopeAnnotationName = scopeAnnotationName;
|
||||
}
|
||||
|
||||
public @Nullable String getScopeAnnotationName() {
|
||||
return this.scopeAnnotationName;
|
||||
}
|
||||
|
||||
public void addQualifierAnnotationName(String qualifierAnnotationName) {
|
||||
this.qualifierAnnotationNames.add(qualifierAnnotationName);
|
||||
}
|
||||
|
||||
public List<String> getQualifierAnnotationNames() {
|
||||
return this.qualifierAnnotationNames;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Apply the given {@link PersistenceManagedTypes} to this persistence unit,
|
||||
* typically coming from Spring AOT.
|
||||
* @param managedTypes the managed persistent types to register
|
||||
* @since 7.0
|
||||
*/
|
||||
public void apply(PersistenceManagedTypes managedTypes) {
|
||||
Assert.notNull(managedTypes, "PersistenceManagedTypes must not be null");
|
||||
managedTypes.getManagedClassNames().forEach(this::addManagedClassName);
|
||||
managedTypes.getManagedPackages().forEach(this::addManagedPackage);
|
||||
URL persistenceUnitRootUrl = managedTypes.getPersistenceUnitRootUrl();
|
||||
if (getPersistenceUnitRootUrl() == null && persistenceUnitRootUrl != null) {
|
||||
setPersistenceUnitRootUrl(persistenceUnitRootUrl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the given JPA 3.2 {@link PersistenceConfiguration} to this persistence unit,
|
||||
* copying all applicable settings.
|
||||
* <p>Beyond the standard {@code PersistenceConfiguration} settings, "rootUrl" and
|
||||
* "jarFileUrls" from {@link org.hibernate.jpa.HibernatePersistenceConfiguration}
|
||||
* are also detected and applied.
|
||||
* @param config the JPA persistence configuration to apply
|
||||
* @param dataSourceLookup the JDBC DataSourceLookup that provides DataSources for the
|
||||
* persistence provider, resolving data source names in {@code PersistenceConfiguration}
|
||||
* against Spring-managed DataSource instances
|
||||
* @since 7.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void apply(PersistenceConfiguration config, DataSourceLookup dataSourceLookup) {
|
||||
Assert.notNull(config, "PersistenceConfiguration must not be null");
|
||||
|
||||
setPersistenceUnitName(config.name());
|
||||
setPersistenceProviderClassName(config.provider());
|
||||
setTransactionType(config.transactionType());
|
||||
|
||||
if (config.nonJtaDataSource() != null) {
|
||||
setNonJtaDataSource(dataSourceLookup.getDataSource(config.nonJtaDataSource()));
|
||||
}
|
||||
if (config.jtaDataSource() != null) {
|
||||
setJtaDataSource(dataSourceLookup.getDataSource(config.jtaDataSource()));
|
||||
}
|
||||
|
||||
config.mappingFiles().forEach(this::addMappingFileName);
|
||||
config.managedClasses().forEach(clazz -> addManagedClassName(clazz.getName()));
|
||||
|
||||
setSharedCacheMode(config.sharedCacheMode());
|
||||
setValidationMode(config.validationMode());
|
||||
getProperties().putAll(config.properties());
|
||||
|
||||
// Further relevant settings from HibernatePersistenceConfiguration
|
||||
Method rootUrl = ClassUtils.getMethodIfAvailable(config.getClass(), "rootUrl");
|
||||
if (rootUrl != null) {
|
||||
setPersistenceUnitRootUrl((URL) ReflectionUtils.invokeMethod(rootUrl, config));
|
||||
}
|
||||
Method jarFileUrls = ClassUtils.getMethodIfAvailable(config.getClass(), "jarFileUrls");
|
||||
if (jarFileUrls != null) {
|
||||
List<URL> urlList = ((List<URL>) ReflectionUtils.invokeMethod(jarFileUrls, config));
|
||||
if (urlList != null) {
|
||||
urlList.forEach(this::addJarFileUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose a standard {@code jakarta.persistence.spi.PersistenceUnitInfo} proxy for the
|
||||
* persistence unit configuration in this {@code SpringPersistenceUnitInfo} instance.
|
||||
@@ -153,7 +244,7 @@ public class SpringPersistenceUnitInfo extends MutablePersistenceUnitInfo {
|
||||
*/
|
||||
private class SmartPersistenceUnitInfoInvocationHandler implements InvocationHandler {
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
@Override
|
||||
public @Nullable Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
// Fast path for SmartPersistenceUnitInfo JTA check
|
||||
|
||||
+10
-10
@@ -39,27 +39,27 @@ public abstract class AbstractEntityManagerFactoryBeanTests {
|
||||
|
||||
protected static EntityManagerFactory mockEmf;
|
||||
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
void setup() {
|
||||
mockEmf = mock();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
void cleanup() {
|
||||
assertThat(TransactionSynchronizationManager.getResourceMap()).isEmpty();
|
||||
assertThat(TransactionSynchronizationManager.isSynchronizationActive()).isFalse();
|
||||
assertThat(TransactionSynchronizationManager.isCurrentTransactionReadOnly()).isFalse();
|
||||
assertThat(TransactionSynchronizationManager.isActualTransactionActive()).isFalse();
|
||||
}
|
||||
|
||||
protected void checkInvariants(AbstractEntityManagerFactoryBean demf) {
|
||||
assertThat(EntityManagerFactory.class.isAssignableFrom(demf.getObjectType())).isTrue();
|
||||
Object gotObject = demf.getObject();
|
||||
boolean condition = gotObject instanceof EntityManagerFactoryInfo;
|
||||
assertThat(condition).as("Object created by factory implements EntityManagerFactoryInfo").isTrue();
|
||||
EntityManagerFactoryInfo emfi = (EntityManagerFactoryInfo) demf.getObject();
|
||||
assertThat(demf.getObject()).as("Successive invocations of getObject() return same object").isSameAs(emfi);
|
||||
assertThat(demf.getObject()).isSameAs(emfi);
|
||||
protected void checkInvariants(AbstractEntityManagerFactoryBean emfb) {
|
||||
assertThat(EntityManagerFactory.class.isAssignableFrom(emfb.getObjectType())).isTrue();
|
||||
EntityManagerFactory emf = emfb.getObject();
|
||||
assertThat(emf instanceof EntityManagerFactoryInfo).as("Object created by factory implements EntityManagerFactoryInfo").isTrue();
|
||||
EntityManagerFactoryInfo emfi = (EntityManagerFactoryInfo) emf;
|
||||
assertThat(emfb.getObject()).as("Successive invocations of getObject() return same object").isSameAs(emfi);
|
||||
assertThat(emfb.getObject()).isSameAs(emfi);
|
||||
assertThat(mockEmf).isSameAs(emfi.getNativeEntityManagerFactory());
|
||||
}
|
||||
|
||||
|
||||
+62
-55
@@ -36,6 +36,8 @@ 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.domain.DriversLicense;
|
||||
import org.springframework.orm.jpa.domain.Person;
|
||||
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
|
||||
@@ -53,23 +55,16 @@ import static org.mockito.Mockito.verify;
|
||||
* @author Juergen Hoeller
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@SuppressWarnings({"rawtypes", "removal"})
|
||||
@SuppressWarnings("rawtypes")
|
||||
class LocalContainerEntityManagerFactoryBeanTests extends AbstractEntityManagerFactoryBeanTests {
|
||||
|
||||
// Static fields set by inner class DummyPersistenceProvider
|
||||
|
||||
private static Map actualProps;
|
||||
|
||||
private static PersistenceUnitInfo actualPui;
|
||||
|
||||
|
||||
@Test
|
||||
void testValidPersistenceUnit() throws Exception {
|
||||
void validPersistenceUnit() {
|
||||
parseValidPersistenceUnit();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExceptionTranslationWithNoDialect() throws Exception {
|
||||
void exceptionTranslationWithNoDialect() {
|
||||
LocalContainerEntityManagerFactoryBean cefb = parseValidPersistenceUnit();
|
||||
cefb.getObject();
|
||||
assertThat(cefb.getJpaDialect()).as("No dialect set").isNull();
|
||||
@@ -83,7 +78,7 @@ class LocalContainerEntityManagerFactoryBeanTests extends AbstractEntityManagerF
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEntityManagerFactoryIsProxied() throws Exception {
|
||||
void entityManagerFactoryIsProxied() throws Exception {
|
||||
LocalContainerEntityManagerFactoryBean cefb = parseValidPersistenceUnit();
|
||||
EntityManagerFactory emf = cefb.getObject();
|
||||
assertThat(cefb.getObject()).as("EntityManagerFactory reference must be cached after init").isSameAs(emf);
|
||||
@@ -100,7 +95,7 @@ class LocalContainerEntityManagerFactoryBeanTests extends AbstractEntityManagerF
|
||||
}
|
||||
|
||||
@Test
|
||||
void testApplicationManagedEntityManagerWithoutTransaction() throws Exception {
|
||||
void applicationManagedEntityManagerWithoutTransaction() {
|
||||
Object testEntity = new Object();
|
||||
EntityManager mockEm = mock();
|
||||
|
||||
@@ -120,7 +115,7 @@ class LocalContainerEntityManagerFactoryBeanTests extends AbstractEntityManagerF
|
||||
}
|
||||
|
||||
@Test
|
||||
void testApplicationManagedEntityManagerWithTransaction() throws Exception {
|
||||
void applicationManagedEntityManagerWithTransaction() {
|
||||
Object testEntity = new Object();
|
||||
|
||||
EntityTransaction mockTx = mock();
|
||||
@@ -161,7 +156,7 @@ class LocalContainerEntityManagerFactoryBeanTests extends AbstractEntityManagerF
|
||||
}
|
||||
|
||||
@Test
|
||||
void testApplicationManagedEntityManagerWithTransactionAndCommitException() throws Exception {
|
||||
void applicationManagedEntityManagerWithTransactionAndCommitException() {
|
||||
Object testEntity = new Object();
|
||||
|
||||
EntityTransaction mockTx = mock();
|
||||
@@ -203,7 +198,7 @@ class LocalContainerEntityManagerFactoryBeanTests extends AbstractEntityManagerF
|
||||
}
|
||||
|
||||
@Test
|
||||
void testApplicationManagedEntityManagerWithJtaTransaction() throws Exception {
|
||||
void applicationManagedEntityManagerWithJtaTransaction() {
|
||||
Object testEntity = new Object();
|
||||
|
||||
// This one's for the tx (shared)
|
||||
@@ -240,68 +235,80 @@ class LocalContainerEntityManagerFactoryBeanTests extends AbstractEntityManagerF
|
||||
verify(mockEmf).close();
|
||||
}
|
||||
|
||||
public LocalContainerEntityManagerFactoryBean parseValidPersistenceUnit(
|
||||
PersistenceUnitPostProcessor... postProcessors) {
|
||||
@Test
|
||||
void invalidPersistenceUnitName() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
createEntityManagerFactoryBean("org/springframework/orm/jpa/domain/persistence.xml", null, "call me Bob"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsMissingPersistenceUnitInfo() {
|
||||
LocalContainerEntityManagerFactoryBean emfb = new LocalContainerEntityManagerFactoryBean();
|
||||
emfb.setPersistenceProviderClass(DummyContainerPersistenceProvider.class);
|
||||
|
||||
String entityManagerName = "call me Bob";
|
||||
emfb.setPersistenceUnitName(entityManagerName);
|
||||
|
||||
assertThatIllegalArgumentException().isThrownBy(emfb::afterPropertiesSet);
|
||||
}
|
||||
|
||||
@Test
|
||||
void acceptsPersistenceConfiguration() {
|
||||
DummyContainerPersistenceProvider persistenceProvider = new DummyContainerPersistenceProvider();
|
||||
LocalContainerEntityManagerFactoryBean emfb = new LocalContainerEntityManagerFactoryBean();
|
||||
emfb.setPersistenceProvider(persistenceProvider);
|
||||
|
||||
String entityManagerName = "call me Bob";
|
||||
emfb.setPersistenceConfiguration(new PersistenceConfiguration(entityManagerName).
|
||||
managedClass(DriversLicense.class).managedClass(Person.class));
|
||||
|
||||
emfb.afterPropertiesSet();
|
||||
assertThat(persistenceProvider.actualPui.getPersistenceUnitName()).isEqualTo(entityManagerName);
|
||||
assertThat(persistenceProvider.actualPui.getManagedClassNames()).containsExactly(
|
||||
DriversLicense.class.getName(), Person.class.getName());
|
||||
}
|
||||
|
||||
|
||||
private LocalContainerEntityManagerFactoryBean parseValidPersistenceUnit(PersistenceUnitPostProcessor... postProcessors) {
|
||||
return createEntityManagerFactoryBean(
|
||||
"org/springframework/orm/jpa/domain/persistence.xml", null,
|
||||
"Person", postProcessors);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidPersistenceUnitName() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
createEntityManagerFactoryBean("org/springframework/orm/jpa/domain/persistence.xml", null, "call me Bob"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected LocalContainerEntityManagerFactoryBean createEntityManagerFactoryBean(
|
||||
private LocalContainerEntityManagerFactoryBean createEntityManagerFactoryBean(
|
||||
String persistenceXml, Properties props, String entityManagerName,
|
||||
PersistenceUnitPostProcessor... postProcessors) {
|
||||
|
||||
// This will be set by DummyPersistenceProvider
|
||||
actualPui = null;
|
||||
actualProps = null;
|
||||
DummyContainerPersistenceProvider persistenceProvider = new DummyContainerPersistenceProvider();
|
||||
LocalContainerEntityManagerFactoryBean emfb = new LocalContainerEntityManagerFactoryBean();
|
||||
|
||||
LocalContainerEntityManagerFactoryBean containerEmfb = new LocalContainerEntityManagerFactoryBean();
|
||||
|
||||
containerEmfb.setPersistenceUnitName(entityManagerName);
|
||||
containerEmfb.setPersistenceProviderClass(DummyContainerPersistenceProvider.class);
|
||||
emfb.setPersistenceUnitName(entityManagerName);
|
||||
emfb.setPersistenceProvider(persistenceProvider);
|
||||
if (props != null) {
|
||||
containerEmfb.setJpaProperties(props);
|
||||
emfb.setJpaProperties(props);
|
||||
}
|
||||
containerEmfb.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
|
||||
containerEmfb.setPersistenceXmlLocation(persistenceXml);
|
||||
containerEmfb.setPersistenceUnitPostProcessors(postProcessors);
|
||||
containerEmfb.afterPropertiesSet();
|
||||
emfb.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
|
||||
emfb.setPersistenceXmlLocation(persistenceXml);
|
||||
emfb.setPersistenceUnitPostProcessors(postProcessors);
|
||||
emfb.afterPropertiesSet();
|
||||
|
||||
assertThat(actualPui.getPersistenceUnitName()).isEqualTo(entityManagerName);
|
||||
assertThat(persistenceProvider.actualPui.getPersistenceUnitName()).isEqualTo(entityManagerName);
|
||||
if (props != null) {
|
||||
assertThat(actualProps).isEqualTo(props);
|
||||
assertThat(persistenceProvider.actualProps).isEqualTo(props);
|
||||
}
|
||||
//checkInvariants(containerEmfb);
|
||||
checkInvariants(emfb);
|
||||
|
||||
return containerEmfb;
|
||||
|
||||
//containerEmfb.destroy();
|
||||
//emfMc.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRejectsMissingPersistenceUnitInfo() {
|
||||
LocalContainerEntityManagerFactoryBean containerEmfb = new LocalContainerEntityManagerFactoryBean();
|
||||
String entityManagerName = "call me Bob";
|
||||
|
||||
containerEmfb.setPersistenceUnitName(entityManagerName);
|
||||
containerEmfb.setPersistenceProviderClass(DummyContainerPersistenceProvider.class);
|
||||
|
||||
assertThatIllegalArgumentException().isThrownBy(
|
||||
containerEmfb::afterPropertiesSet);
|
||||
return emfb;
|
||||
}
|
||||
|
||||
|
||||
private static class DummyContainerPersistenceProvider implements PersistenceProvider {
|
||||
|
||||
PersistenceUnitInfo actualPui;
|
||||
|
||||
Map actualProps;
|
||||
|
||||
@Override
|
||||
public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo pui, Map map) {
|
||||
actualPui = pui;
|
||||
|
||||
+108
-34
@@ -27,64 +27,138 @@ import jakarta.persistence.spi.ProviderUtil;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
class LocalEntityManagerFactoryBeanTests extends AbstractEntityManagerFactoryBeanTests {
|
||||
|
||||
// Static fields set by inner class DummyPersistenceProvider
|
||||
|
||||
private static String actualName;
|
||||
|
||||
private static Map actualProps;
|
||||
|
||||
@AfterEach
|
||||
void verifyClosed() {
|
||||
verify(mockEmf).close();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testValidUsageWithDefaultProperties() throws Exception {
|
||||
testValidUsage(null);
|
||||
void withDefault() {
|
||||
DummyPersistenceProvider persistenceProvider = new DummyPersistenceProvider();
|
||||
LocalEntityManagerFactoryBean emfb = new LocalEntityManagerFactoryBean();
|
||||
|
||||
emfb.setPersistenceProvider(persistenceProvider);
|
||||
emfb.afterPropertiesSet();
|
||||
|
||||
assertThat(persistenceProvider.actualName).isSameAs(
|
||||
DefaultPersistenceUnitManager.ORIGINAL_DEFAULT_PERSISTENCE_UNIT_NAME);
|
||||
assertThat(persistenceProvider.actualProps).isEqualTo(emfb.getJpaPropertyMap());
|
||||
checkInvariants(emfb);
|
||||
|
||||
emfb.destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValidUsageWithExplicitProperties() throws Exception {
|
||||
testValidUsage(new Properties());
|
||||
void withName() {
|
||||
DummyPersistenceProvider persistenceProvider = new DummyPersistenceProvider();
|
||||
LocalEntityManagerFactoryBean emfb = new LocalEntityManagerFactoryBean();
|
||||
String name = "call me Bob";
|
||||
|
||||
emfb.setPersistenceUnitName(name);
|
||||
emfb.setPersistenceProvider(persistenceProvider);
|
||||
emfb.afterPropertiesSet();
|
||||
|
||||
assertThat(persistenceProvider.actualName).isSameAs(name);
|
||||
assertThat(persistenceProvider.actualProps).isEqualTo(emfb.getJpaPropertyMap());
|
||||
checkInvariants(emfb);
|
||||
|
||||
emfb.destroy();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void testValidUsage(Properties props) {
|
||||
// This will be set by DummyPersistenceProvider
|
||||
actualName = null;
|
||||
actualProps = null;
|
||||
@Test
|
||||
void withNameAndExplicitProperties() {
|
||||
DummyPersistenceProvider persistenceProvider = new DummyPersistenceProvider();
|
||||
LocalEntityManagerFactoryBean emfb = new LocalEntityManagerFactoryBean();
|
||||
String name = "call me Bob";
|
||||
Properties props = new Properties();
|
||||
props.setProperty("myProp", "myVal");
|
||||
|
||||
LocalEntityManagerFactoryBean lemfb = new LocalEntityManagerFactoryBean();
|
||||
String entityManagerName = "call me Bob";
|
||||
emfb.setPersistenceUnitName(name);
|
||||
emfb.setPersistenceProvider(persistenceProvider);
|
||||
emfb.setJpaProperties(props);
|
||||
emfb.afterPropertiesSet();
|
||||
|
||||
lemfb.setPersistenceUnitName(entityManagerName);
|
||||
lemfb.setPersistenceProviderClass(DummyPersistenceProvider.class);
|
||||
if (props != null) {
|
||||
lemfb.setJpaProperties(props);
|
||||
}
|
||||
lemfb.afterPropertiesSet();
|
||||
assertThat(persistenceProvider.actualName).isSameAs(name);
|
||||
assertThat(persistenceProvider.actualProps).isEqualTo(props);
|
||||
checkInvariants(emfb);
|
||||
|
||||
assertThat(actualName).isSameAs(entityManagerName);
|
||||
if (props != null) {
|
||||
assertThat(actualProps).isEqualTo(props);
|
||||
}
|
||||
checkInvariants(lemfb);
|
||||
emfb.destroy();
|
||||
}
|
||||
|
||||
lemfb.destroy();
|
||||
@Test
|
||||
void withDefaultPersistenceConfiguration() {
|
||||
DummyPersistenceProvider persistenceProvider = new DummyPersistenceProvider();
|
||||
LocalEntityManagerFactoryBean emfb = new LocalEntityManagerFactoryBean();
|
||||
|
||||
emfb.getPersistenceConfiguration().property("myProp", "myVal");
|
||||
emfb.setPersistenceProvider(persistenceProvider);
|
||||
emfb.afterPropertiesSet();
|
||||
|
||||
assertThat(persistenceProvider.actualName).isSameAs(
|
||||
DefaultPersistenceUnitManager.ORIGINAL_DEFAULT_PERSISTENCE_UNIT_NAME);
|
||||
assertThat(persistenceProvider.actualProps).containsEntry("myProp", "myVal");
|
||||
checkInvariants(emfb);
|
||||
|
||||
emfb.destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
void withNameAndDefaultPersistenceConfiguration() {
|
||||
DummyPersistenceProvider persistenceProvider = new DummyPersistenceProvider();
|
||||
LocalEntityManagerFactoryBean emfb = new LocalEntityManagerFactoryBean();
|
||||
String name = "call me Bob";
|
||||
|
||||
emfb.setPersistenceUnitName(name);
|
||||
emfb.getPersistenceConfiguration().property("myProp", "myVal");
|
||||
emfb.setPersistenceProvider(persistenceProvider);
|
||||
emfb.afterPropertiesSet();
|
||||
|
||||
assertThat(persistenceProvider.actualName).isSameAs(name);
|
||||
assertThat(persistenceProvider.actualProps).containsEntry("myProp", "myVal");
|
||||
checkInvariants(emfb);
|
||||
|
||||
emfb.destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
void withExplicitPersistenceConfiguration() {
|
||||
DummyPersistenceProvider persistenceProvider = new DummyPersistenceProvider();
|
||||
LocalEntityManagerFactoryBean emfb = new LocalEntityManagerFactoryBean();
|
||||
String name = "call me Bob";
|
||||
PersistenceConfiguration config = new PersistenceConfiguration(name);
|
||||
config.property("myProp", "myVal");
|
||||
|
||||
emfb.setPersistenceConfiguration(config);
|
||||
emfb.setPersistenceProvider(persistenceProvider);
|
||||
emfb.afterPropertiesSet();
|
||||
|
||||
assertThat(persistenceProvider.actualName).isSameAs(name);
|
||||
assertThat(persistenceProvider.actualProps).containsEntry("myProp", "myVal");
|
||||
checkInvariants(emfb);
|
||||
|
||||
emfb.destroy();
|
||||
}
|
||||
|
||||
|
||||
protected static class DummyPersistenceProvider implements PersistenceProvider {
|
||||
private static class DummyPersistenceProvider implements PersistenceProvider {
|
||||
|
||||
String actualName;
|
||||
|
||||
Map actualProps;
|
||||
|
||||
@Override
|
||||
public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo pui, Map map) {
|
||||
@@ -99,8 +173,10 @@ class LocalEntityManagerFactoryBeanTests extends AbstractEntityManagerFactoryBea
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityManagerFactory createEntityManagerFactory(PersistenceConfiguration persistenceConfiguration) {
|
||||
throw new UnsupportedOperationException();
|
||||
public EntityManagerFactory createEntityManagerFactory(PersistenceConfiguration config) {
|
||||
actualName = config.name();
|
||||
actualProps = config.properties();
|
||||
return mockEmf;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -108,13 +184,11 @@ class LocalEntityManagerFactoryBeanTests extends AbstractEntityManagerFactoryBea
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
// JPA 2.1 method
|
||||
@Override
|
||||
public void generateSchema(PersistenceUnitInfo persistenceUnitInfo, Map map) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
// JPA 2.1 method
|
||||
@Override
|
||||
public boolean generateSchema(String persistenceUnitName, Map map) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
-1
@@ -46,7 +46,6 @@ import static org.assertj.core.api.Assertions.assertThatRuntimeException;
|
||||
* @author Juergen Hoeller
|
||||
* @author Nicholas Williams
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
class PersistenceXmlParsingTests {
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user