mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-17 16:39:29 +00:00
Revise PersistenceUnitInfo management for compatibility with JPA 3.2/4.0
Closes gh-35622
This commit is contained in:
+2
-3
@@ -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);
|
||||
}
|
||||
|
||||
+12
-13
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-50
@@ -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 +
|
||||
|
||||
+9
-7
@@ -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);
|
||||
|
||||
|
||||
+1
-2
@@ -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 {
|
||||
|
||||
|
||||
+9
@@ -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();
|
||||
|
||||
}
|
||||
|
||||
+44
-3
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -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
|
||||
|
||||
+11
-8
@@ -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);
|
||||
|
||||
+6
-9
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+21
-22
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user