diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean.java b/spring-orm/src/main/java/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean.java index 87de3cc71da..94fa087dead 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean.java @@ -21,6 +21,7 @@ import java.util.List; import javax.sql.DataSource; import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.FetchType; import jakarta.persistence.PersistenceConfiguration; import jakarta.persistence.PersistenceException; import jakarta.persistence.SharedCacheMode; @@ -287,6 +288,17 @@ public class LocalContainerEntityManagerFactoryBean extends AbstractEntityManage this.internalPersistenceUnitManager.setValidationMode(validationMode); } + /** + * Specify the JPA 4.0 default fetch type for all of this manager's persistence + * units, overriding any value in {@code persistence.xml} if set. + *
NOTE: Only applied if no external PersistenceUnitManager specified. Also, + * this requires a JPA 4.0+ persistence provider and will be ignored otherwise. + * @since 7.0.4 + */ + public void setDefaultToOneFetchType(FetchType defaultToOneFetchType) { + this.internalPersistenceUnitManager.setDefaultToOneFetchType(defaultToOneFetchType); + } + /** * Specify the JDBC DataSource that the JPA persistence provider is supposed * to use for accessing the database. This is an alternative to keeping the diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/DefaultPersistenceUnitManager.java b/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/DefaultPersistenceUnitManager.java index c014ef43fc1..2bbdf5ca715 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/DefaultPersistenceUnitManager.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/DefaultPersistenceUnitManager.java @@ -27,6 +27,7 @@ import java.util.Set; import javax.sql.DataSource; +import jakarta.persistence.FetchType; import jakarta.persistence.PersistenceConfiguration; import jakarta.persistence.PersistenceException; import jakarta.persistence.SharedCacheMode; @@ -123,6 +124,8 @@ public class DefaultPersistenceUnitManager private @Nullable ValidationMode validationMode; + private @Nullable FetchType defaultToOneFetchType; + private DataSourceLookup dataSourceLookup = new JndiDataSourceLookup(); private @Nullable DataSource defaultDataSource; @@ -291,6 +294,17 @@ public class DefaultPersistenceUnitManager this.validationMode = validationMode; } + /** + * Specify the JPA 4.0 default fetch type for all of this manager's persistence + * units, overriding any value in {@code persistence.xml} if set. + *
This setting only applies against a JPA 4.0+ persistence provider.
+ * Otherwise, it will be ignored.
+ * @since 7.0.4
+ */
+ public void setDefaultToOneFetchType(FetchType defaultToOneFetchType) {
+ this.defaultToOneFetchType = defaultToOneFetchType;
+ }
+
/**
* Specify the JDBC DataSources that the JPA persistence provider is supposed
* to use for accessing the database, resolving data source names in
@@ -475,6 +489,9 @@ public class DefaultPersistenceUnitManager
if (this.validationMode != null) {
pui.setValidationMode(this.validationMode);
}
+ if (this.defaultToOneFetchType != null) {
+ pui.setDefaultToOneFetchType(this.defaultToOneFetchType);
+ }
// Initialize persistence unit ClassLoader
if (this.loadTimeWeaver != null) {
diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/MutablePersistenceUnitInfo.java b/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/MutablePersistenceUnitInfo.java
index 5a66df719aa..f5d7ac215da 100644
--- a/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/MutablePersistenceUnitInfo.java
+++ b/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/MutablePersistenceUnitInfo.java
@@ -23,6 +23,7 @@ import java.util.Properties;
import javax.sql.DataSource;
+import jakarta.persistence.FetchType;
import jakarta.persistence.PersistenceUnitTransactionType;
import jakarta.persistence.SharedCacheMode;
import jakarta.persistence.ValidationMode;
@@ -82,6 +83,8 @@ public class MutablePersistenceUnitInfo {
private ValidationMode validationMode = ValidationMode.AUTO;
+ private FetchType defaultToOneFetchType = FetchType.EAGER;
+
private Properties properties = new Properties();
private String persistenceXMLSchemaVersion = "3.2";
@@ -213,6 +216,14 @@ public class MutablePersistenceUnitInfo {
return this.validationMode;
}
+ public void setDefaultToOneFetchType(FetchType defaultToOneFetchType) {
+ this.defaultToOneFetchType = defaultToOneFetchType;
+ }
+
+ public FetchType getDefaultToOneFetchType() {
+ return this.defaultToOneFetchType;
+ }
+
public void addProperty(String name, String value) {
this.properties.setProperty(name, value);
}
diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/PersistenceUnitReader.java b/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/PersistenceUnitReader.java
index ab1fe866387..941d9e54916 100644
--- a/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/PersistenceUnitReader.java
+++ b/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/PersistenceUnitReader.java
@@ -26,6 +26,7 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
+import jakarta.persistence.FetchType;
import jakarta.persistence.PersistenceUnitTransactionType;
import jakarta.persistence.SharedCacheMode;
import jakarta.persistence.ValidationMode;
@@ -85,6 +86,8 @@ final class PersistenceUnitReader {
private static final String VALIDATION_MODE = "validation-mode";
+ private static final String DEFAULT_TO_ONE_FETCH_TYPE = "default-to-one-fetch-type";
+
private static final String PROPERTIES = "properties";
private static final String META_INF = "META-INF";
@@ -251,6 +254,12 @@ final class PersistenceUnitReader {
unitInfo.setValidationMode(ValidationMode.valueOf(validationMode));
}
+ // set JPA 4.0 default fetch type
+ String fetchType = DomUtils.getChildElementValueByTagName(persistenceUnit, DEFAULT_TO_ONE_FETCH_TYPE);
+ if (StringUtils.hasText(fetchType)) {
+ unitInfo.setDefaultToOneFetchType(FetchType.valueOf(fetchType));
+ }
+
parseQualifiers(persistenceUnit, unitInfo);
parseMappingFiles(persistenceUnit, unitInfo);
parseJarFiles(persistenceUnit, unitInfo);
diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/SpringPersistenceUnitInfo.java b/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/SpringPersistenceUnitInfo.java
index a2819332b68..6141eaa62e7 100644
--- a/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/SpringPersistenceUnitInfo.java
+++ b/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/SpringPersistenceUnitInfo.java
@@ -23,6 +23,7 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.List;
+import jakarta.persistence.FetchType;
import jakarta.persistence.PersistenceConfiguration;
import jakarta.persistence.PersistenceUnitTransactionType;
import jakarta.persistence.spi.ClassTransformer;
@@ -207,6 +208,16 @@ public class SpringPersistenceUnitInfo extends MutablePersistenceUnitInfo {
setSharedCacheMode(config.sharedCacheMode());
setValidationMode(config.validationMode());
+
+ // JPA 4.0 defaultToOneFetchType
+ Method defaultToOneFetchType = ClassUtils.getMethodIfAvailable(config.getClass(), "defaultToOneFetchType");
+ if (defaultToOneFetchType != null) {
+ FetchType fetchType = (FetchType) ReflectionUtils.invokeMethod(defaultToOneFetchType, config);
+ if (fetchType != null) {
+ setDefaultToOneFetchType(fetchType);
+ }
+ }
+
getProperties().putAll(config.properties());
// Further relevant settings from HibernatePersistenceConfiguration on Hibernate 7.1+
@@ -247,10 +258,21 @@ public class SpringPersistenceUnitInfo extends MutablePersistenceUnitInfo {
@SuppressWarnings({"rawtypes", "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")) {
+ // Fast path for SmartPersistenceUnitInfo JTA check
return (getTransactionType() == PersistenceUnitTransactionType.JTA);
}
+ else if (method.getName().equals("getAllManagedClassNames")) {
+ // JPA 4.0 letting the container perform the scanning ->
+ // with Spring, only makes sense with typical default persistence unit.
+ if (excludeUnlistedClasses() && getMappingFileNames().isEmpty()) {
+ List