Skip to content

Commit 8ef25c5

Browse files
Polishing.
Limit ability to override properties. Original Pull Request: #4106
1 parent de0fc92 commit 8ef25c5

File tree

3 files changed

+106
-19
lines changed

3 files changed

+106
-19
lines changed

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/aot/AotMetamodel.java

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
import java.net.URL;
2828
import java.util.Collection;
29-
import java.util.LinkedHashMap;
3029
import java.util.Map;
3130
import java.util.Set;
3231
import java.util.function.Supplier;
@@ -45,9 +44,12 @@
4544
import org.hibernate.jpa.boot.internal.PersistenceUnitInfoDescriptor;
4645
import org.hibernate.query.common.TemporalUnit;
4746
import org.jspecify.annotations.Nullable;
47+
import org.slf4j.Logger;
48+
import org.slf4j.LoggerFactory;
4849
import org.springframework.data.util.Lazy;
4950
import org.springframework.orm.jpa.persistenceunit.PersistenceManagedTypes;
5051
import org.springframework.orm.jpa.persistenceunit.SpringPersistenceUnitInfo;
52+
import org.springframework.util.CollectionUtils;
5153

5254
/**
5355
* AOT metamodel implementation that uses Hibernate to build the metamodel.
@@ -59,6 +61,17 @@
5961
*/
6062
class AotMetamodel implements Metamodel {
6163

64+
private static final Logger log = LoggerFactory.getLogger(AotMetamodel.class);
65+
66+
/**
67+
* Collection of know properties causing problems during AOT if set differntly
68+
*/
69+
private static final Map<String, Object> FAILSAFE_AOT_PROPERTIES = Map.of( //
70+
JdbcSettings.ALLOW_METADATA_ON_BOOT, false, //
71+
JdbcSettings.CONNECTION_PROVIDER, NoOpConnectionProvider.INSTANCE, //
72+
QuerySettings.QUERY_STARTUP_CHECKING, false, //
73+
PersistenceSettings.JPA_CALLBACKS_ENABLED, false //
74+
);
6275
private final Lazy<EntityManagerFactory> entityManagerFactory;
6376
private final Lazy<EntityManager> entityManager = Lazy.of(() -> getEntityManagerFactory().createEntityManager());
6477

@@ -89,18 +102,37 @@ public AotMetamodel(PersistenceUnitInfo unitInfo, Map<String, Object> jpaPropert
89102

90103
static Lazy<EntityManagerFactory> init(Supplier<PersistenceUnitInfoDescriptor> unitInfo,
91104
Map<String, Object> jpaProperties) {
105+
return Lazy.of(() -> new EntityManagerFactoryBuilderImpl(unitInfo.get(), initProperties(jpaProperties)).build());
106+
}
107+
108+
static Map<String, Object> initProperties(Map<String, Object> jpaProperties) {
109+
110+
Map<String, Object> properties = CollectionUtils
111+
.newLinkedHashMap(jpaProperties.size() + FAILSAFE_AOT_PROPERTIES.size() + 1);
92112

93-
Map<String, Object> properties = new LinkedHashMap<>();
94-
properties.putAll(Map.of(JdbcSettings.DIALECT, SpringDataJpaAotDialect.INSTANCE, //
95-
JdbcSettings.ALLOW_METADATA_ON_BOOT, false, //
96-
JdbcSettings.CONNECTION_PROVIDER, new UserSuppliedConnectionProviderImpl(), //
97-
QuerySettings.QUERY_STARTUP_CHECKING, false, //
98-
PersistenceSettings.JPA_CALLBACKS_ENABLED, false));
113+
// we allow explicit Dialect Overrides, but put in a default one to avoid potential db access
114+
properties.put(JdbcSettings.DIALECT, SpringDataJpaAotDialect.INSTANCE);
99115

116+
// apply user defined properties
100117
properties.putAll(jpaProperties);
101118

102-
return Lazy.of(() -> new EntityManagerFactoryBuilderImpl(unitInfo.get(), properties)
103-
.build());
119+
// override properties known to cause trouble
120+
applyPropertyOverrides(properties);
121+
122+
return properties;
123+
}
124+
125+
private static void applyPropertyOverrides(Map<String, Object> properties) {
126+
127+
for (Map.Entry<String, Object> entry : FAILSAFE_AOT_PROPERTIES.entrySet()) {
128+
129+
if (log.isDebugEnabled() && properties.containsKey(entry.getKey())) {
130+
log.debug("Overriding property [%s] with value [%s] for AOT Repository processing.".formatted(entry.getKey(),
131+
entry.getValue()));
132+
}
133+
134+
properties.put(entry.getKey(), entry.getValue());
135+
}
104136
}
105137

106138
private Metamodel getMetamodel() {
@@ -182,4 +214,14 @@ public String timestampdiffPattern(TemporalUnit unit, TemporalType fromTemporalT
182214

183215
}
184216

217+
static class NoOpConnectionProvider extends UserSuppliedConnectionProviderImpl {
218+
219+
static final NoOpConnectionProvider INSTANCE = new NoOpConnectionProvider();
220+
221+
@Override
222+
public String toString() {
223+
return "NoOpConnectionProvider";
224+
}
225+
}
226+
185227
}

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtension.java

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,6 @@ protected void configureTypeContribution(Class<?> type, AotContext aotContext) {
408408

409409
ConfigurableListableBeanFactory beanFactory = repositoryContext.getBeanFactory();
410410
Environment environment = repositoryContext.getEnvironment();
411-
JpaProperties properties = new JpaProperties(environment);
412411
boolean useEntityManager = environment.getProperty(USE_ENTITY_MANAGER, Boolean.class, false);
413412

414413
if (useEntityManager) {
@@ -425,6 +424,7 @@ protected void configureTypeContribution(Class<?> type, AotContext aotContext) {
425424
return new JpaRepositoryContributor(repositoryContext, emf);
426425
}
427426

427+
JpaProperties properties = new JpaProperties(environment);
428428
ObjectProvider<PersistenceManagedTypes> managedTypesProvider = beanFactory
429429
.getBeanProvider(PersistenceManagedTypes.class);
430430
PersistenceManagedTypes managedTypes = managedTypesProvider.getIfUnique();
@@ -466,18 +466,14 @@ public JpaProperties(Environment environment) {
466466

467467
this.jpaProperties = new LinkedHashMap<>();
468468

469-
String implicitStrategy = environment.getProperty("spring.jpa.hibernate.naming.implicitStrategy");
470-
if (implicitStrategy == null) {
471-
implicitStrategy = environment.getProperty("spring.jpa.hibernate.naming.implicit-strategy");
472-
}
469+
String implicitStrategy = getFirstAvailable(environment, "spring.jpa.hibernate.naming.implicitStrategy",
470+
"spring.jpa.hibernate.naming.implicit-strategy");
473471
if (StringUtils.hasText(implicitStrategy)) {
474472
jpaProperties.put(MappingSettings.IMPLICIT_NAMING_STRATEGY, implicitStrategy);
475473
}
476474

477-
String physicalStrategy = environment.getProperty("spring.jpa.hibernate.naming.physicalStrategy");
478-
if (physicalStrategy == null) {
479-
physicalStrategy = environment.getProperty("spring.jpa.hibernate.naming.physical-strategy");
480-
}
475+
String physicalStrategy = getFirstAvailable(environment, "spring.jpa.hibernate.naming.physicalStrategy",
476+
"spring.jpa.hibernate.naming.physical-strategy");
481477
if (StringUtils.hasText(physicalStrategy)) {
482478
jpaProperties.put(MappingSettings.PHYSICAL_NAMING_STRATEGY, physicalStrategy);
483479
}
@@ -499,6 +495,18 @@ public JpaProperties(Environment environment) {
499495
}
500496
}
501497

498+
@Nullable
499+
String getFirstAvailable(Environment environment, String... propertyNames) {
500+
501+
for (String propertyName : propertyNames) {
502+
String value = environment.getProperty(propertyName);
503+
if (value != null) {
504+
return value;
505+
}
506+
}
507+
return null;
508+
}
509+
502510
public Map<String, Object> getJpaProperties() {
503511
return jpaProperties;
504512
}

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/aot/AotMetamodelUnitTests.java

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,19 @@
1515
*/
1616
package org.springframework.data.jpa.repository.aot;
1717

18-
import static org.assertj.core.api.Assertions.*;
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
20+
import java.util.Map;
1921

2022
import org.junit.jupiter.api.Test;
23+
import org.springframework.data.jpa.repository.aot.AotMetamodel.NoOpConnectionProvider;
24+
import org.springframework.data.jpa.repository.aot.AotMetamodel.SpringDataJpaAotDialect;
2125

2226
/**
2327
* Unit tests for {@link AotMetamodel}.
2428
*
2529
* @author Mark Paluch
30+
* @author Christoph Strobl
2631
*/
2732
class AotMetamodelUnitTests {
2833

@@ -31,4 +36,36 @@ void dialectSupportsSequences() {
3136
assertThat(AotMetamodel.SpringDataJpaAotDialect.INSTANCE.getSequenceSupport().supportsSequences()).isTrue();
3237
assertThat(AotMetamodel.SpringDataJpaAotDialect.INSTANCE.getSequenceSupport().supportsPooledSequences()).isTrue();
3338
}
39+
40+
@Test // GH-4092
41+
void intializesPropertiesWithDefaults() {
42+
43+
assertThat(AotMetamodel.initProperties(Map.of())) //
44+
.containsEntry("hibernate.dialect", SpringDataJpaAotDialect.INSTANCE) //
45+
.containsEntry("hibernate.boot.allow_jdbc_metadata_access", false) //
46+
.containsEntry("hibernate.connection.provider_class", NoOpConnectionProvider.INSTANCE) //
47+
.containsEntry("hibernate.jpa_callbacks.enabled", false) //
48+
.containsEntry("hibernate.query.startup_check", false);
49+
}
50+
51+
@Test // GH-4092
52+
void allowsDialectOverridesViaProperties() {
53+
54+
assertThat(AotMetamodel.initProperties(Map.of("hibernate.dialect", "H2Dialect", "jpa.bla.bla", "42")))
55+
.containsEntry("hibernate.dialect", "H2Dialect") //
56+
.containsEntry("jpa.bla.bla", "42");
57+
}
58+
59+
@Test // GH-4092
60+
void preventsPropertyOverrides/* for cases we know cause trouble */() {
61+
62+
assertThat(AotMetamodel.initProperties(Map.of(//
63+
"hibernate.boot.allow_jdbc_metadata_access", "true", //
64+
"hibernate.connection.provider_class", "DatasourceConnectionProviderImpl", //
65+
"hibernate.jpa_callbacks.enabled", "true", //
66+
"hibernate.query.startup_check", "true"))).containsEntry("hibernate.boot.allow_jdbc_metadata_access", false) //
67+
.containsEntry("hibernate.connection.provider_class", NoOpConnectionProvider.INSTANCE) //
68+
.containsEntry("hibernate.jpa_callbacks.enabled", false) //
69+
.containsEntry("hibernate.query.startup_check", false);
70+
}
3471
}

0 commit comments

Comments
 (0)