Commit c22e9a55 authored by Stephane Nicoll's avatar Stephane Nicoll

Make sure that JpaProperties does not have Hibernate imports

This commit removes Hibernate imports from JpaProperties so that it can
be used with another JPA provider.

This commit is a breaking change for an internal, yet public class used
to transmit customizations provided by the user. It does not change the
external functionality though: naming strategies defined as bean are
still taken into account and a customizer has a chance to override it
regardless.

Closes gh-13043
parent 6556bb2e
...@@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.orm.jpa; ...@@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.orm.jpa;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Supplier; import java.util.function.Supplier;
...@@ -84,10 +85,6 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration { ...@@ -84,10 +85,6 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
private DataSourcePoolMetadataProvider poolMetadataProvider; private DataSourcePoolMetadataProvider poolMetadataProvider;
private final PhysicalNamingStrategy physicalNamingStrategy;
private final ImplicitNamingStrategy implicitNamingStrategy;
private final List<HibernatePropertiesCustomizer> hibernatePropertiesCustomizers; private final List<HibernatePropertiesCustomizer> hibernatePropertiesCustomizers;
HibernateJpaConfiguration(DataSource dataSource, JpaProperties jpaProperties, HibernateJpaConfiguration(DataSource dataSource, JpaProperties jpaProperties,
...@@ -104,10 +101,23 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration { ...@@ -104,10 +101,23 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
providers.getIfAvailable(Collections::emptyList)); providers.getIfAvailable(Collections::emptyList));
this.poolMetadataProvider = new CompositeDataSourcePoolMetadataProvider( this.poolMetadataProvider = new CompositeDataSourcePoolMetadataProvider(
metadataProviders.getIfAvailable()); metadataProviders.getIfAvailable());
this.physicalNamingStrategy = physicalNamingStrategy.getIfAvailable(); this.hibernatePropertiesCustomizers = determineHibernatePropertiesCustomizers(
this.implicitNamingStrategy = implicitNamingStrategy.getIfAvailable(); physicalNamingStrategy.getIfAvailable(),
this.hibernatePropertiesCustomizers = hibernatePropertiesCustomizers implicitNamingStrategy.getIfAvailable(),
.getIfAvailable(() -> Collections.emptyList()); hibernatePropertiesCustomizers.getIfAvailable(Collections::emptyList));
}
private List<HibernatePropertiesCustomizer> determineHibernatePropertiesCustomizers(
PhysicalNamingStrategy physicalNamingStrategy,
ImplicitNamingStrategy implicitNamingStrategy,
List<HibernatePropertiesCustomizer> hibernatePropertiesCustomizers) {
if (physicalNamingStrategy != null || implicitNamingStrategy != null) {
LinkedList<HibernatePropertiesCustomizer> customizers = new LinkedList<>(hibernatePropertiesCustomizers);
customizers.addFirst(new NamingStrategiesHibernatePropertiesCustomizer(
physicalNamingStrategy, implicitNamingStrategy));
return customizers;
}
return hibernatePropertiesCustomizers;
} }
@Override @Override
...@@ -121,8 +131,6 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration { ...@@ -121,8 +131,6 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
.getDefaultDdlAuto(getDataSource()); .getDefaultDdlAuto(getDataSource());
return new LinkedHashMap<>(getProperties() return new LinkedHashMap<>(getProperties()
.getHibernateProperties(new HibernateSettings().ddlAuto(defaultDdlMode) .getHibernateProperties(new HibernateSettings().ddlAuto(defaultDdlMode)
.implicitNamingStrategy(this.implicitNamingStrategy)
.physicalNamingStrategy(this.physicalNamingStrategy)
.hibernatePropertiesCustomizers( .hibernatePropertiesCustomizers(
this.hibernatePropertiesCustomizers))); this.hibernatePropertiesCustomizers)));
} }
...@@ -232,4 +240,32 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration { ...@@ -232,4 +240,32 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
throw new IllegalStateException("Could not configure JTA platform"); throw new IllegalStateException("Could not configure JTA platform");
} }
private static class NamingStrategiesHibernatePropertiesCustomizer
implements HibernatePropertiesCustomizer {
private final PhysicalNamingStrategy physicalNamingStrategy;
private final ImplicitNamingStrategy implicitNamingStrategy;
NamingStrategiesHibernatePropertiesCustomizer(
PhysicalNamingStrategy physicalNamingStrategy,
ImplicitNamingStrategy implicitNamingStrategy) {
this.physicalNamingStrategy = physicalNamingStrategy;
this.implicitNamingStrategy = implicitNamingStrategy;
}
@Override
public void customize(Map<String, Object> hibernateProperties) {
if (this.physicalNamingStrategy != null) {
hibernateProperties.put("hibernate.physical_naming_strategy",
this.physicalNamingStrategy);
}
if (this.implicitNamingStrategy != null) {
hibernateProperties.put("hibernate.implicit_naming_strategy",
this.implicitNamingStrategy);
}
}
}
} }
...@@ -20,9 +20,6 @@ import java.util.ArrayList; ...@@ -20,9 +20,6 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
/** /**
* Settings to apply when configuring Hibernate. * Settings to apply when configuring Hibernate.
* *
...@@ -33,10 +30,6 @@ public class HibernateSettings { ...@@ -33,10 +30,6 @@ public class HibernateSettings {
private Supplier<String> ddlAuto; private Supplier<String> ddlAuto;
private ImplicitNamingStrategy implicitNamingStrategy;
private PhysicalNamingStrategy physicalNamingStrategy;
private Collection<HibernatePropertiesCustomizer> hibernatePropertiesCustomizers; private Collection<HibernatePropertiesCustomizer> hibernatePropertiesCustomizers;
public HibernateSettings ddlAuto(Supplier<String> ddlAuto) { public HibernateSettings ddlAuto(Supplier<String> ddlAuto) {
...@@ -60,26 +53,6 @@ public class HibernateSettings { ...@@ -60,26 +53,6 @@ public class HibernateSettings {
return (this.ddlAuto != null ? this.ddlAuto.get() : null); return (this.ddlAuto != null ? this.ddlAuto.get() : null);
} }
public HibernateSettings implicitNamingStrategy(
ImplicitNamingStrategy implicitNamingStrategy) {
this.implicitNamingStrategy = implicitNamingStrategy;
return this;
}
public ImplicitNamingStrategy getImplicitNamingStrategy() {
return this.implicitNamingStrategy;
}
public HibernateSettings physicalNamingStrategy(
PhysicalNamingStrategy physicalNamingStrategy) {
this.physicalNamingStrategy = physicalNamingStrategy;
return this;
}
public PhysicalNamingStrategy getPhysicalNamingStrategy() {
return this.physicalNamingStrategy;
}
public HibernateSettings hibernatePropertiesCustomizers( public HibernateSettings hibernatePropertiesCustomizers(
Collection<HibernatePropertiesCustomizer> hibernatePropertiesCustomizers) { Collection<HibernatePropertiesCustomizer> hibernatePropertiesCustomizers) {
this.hibernatePropertiesCustomizers = new ArrayList<>( this.hibernatePropertiesCustomizers = new ArrayList<>(
......
...@@ -25,9 +25,6 @@ import java.util.function.Supplier; ...@@ -25,9 +25,6 @@ import java.util.function.Supplier;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.orm.jpa.vendor.Database; import org.springframework.orm.jpa.vendor.Database;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
...@@ -215,9 +212,7 @@ public class JpaProperties { ...@@ -215,9 +212,7 @@ public class JpaProperties {
HibernateSettings settings) { HibernateSettings settings) {
Map<String, Object> result = new HashMap<>(existing); Map<String, Object> result = new HashMap<>(existing);
applyNewIdGeneratorMappings(result); applyNewIdGeneratorMappings(result);
getNaming().applyNamingStrategies(result, getNaming().applyNamingStrategies(result);
settings.getImplicitNamingStrategy(),
settings.getPhysicalNamingStrategy());
String ddlAuto = determineDdlAuto(existing, settings::getDdlAuto); String ddlAuto = determineDdlAuto(existing, settings::getDdlAuto);
if (StringUtils.hasText(ddlAuto) && !"none".equals(ddlAuto)) { if (StringUtils.hasText(ddlAuto) && !"none".equals(ddlAuto)) {
result.put("hibernate.hbm2ddl.auto", ddlAuto); result.put("hibernate.hbm2ddl.auto", ddlAuto);
...@@ -292,17 +287,11 @@ public class JpaProperties { ...@@ -292,17 +287,11 @@ public class JpaProperties {
this.physicalStrategy = physicalStrategy; this.physicalStrategy = physicalStrategy;
} }
private void applyNamingStrategies(Map<String, Object> properties, private void applyNamingStrategies(Map<String, Object> properties) {
ImplicitNamingStrategy implicitStrategyBean,
PhysicalNamingStrategy physicalStrategyBean) {
applyNamingStrategy(properties, "hibernate.implicit_naming_strategy", applyNamingStrategy(properties, "hibernate.implicit_naming_strategy",
implicitStrategyBean != null ? implicitStrategyBean this.implicitStrategy, DEFAULT_IMPLICIT_STRATEGY);
: this.implicitStrategy,
DEFAULT_IMPLICIT_STRATEGY);
applyNamingStrategy(properties, "hibernate.physical_naming_strategy", applyNamingStrategy(properties, "hibernate.physical_naming_strategy",
physicalStrategyBean != null ? physicalStrategyBean this.physicalStrategy, DEFAULT_PHYSICAL_STRATEGY);
: this.physicalStrategy,
DEFAULT_PHYSICAL_STRATEGY);
} }
private void applyNamingStrategy(Map<String, Object> properties, String key, private void applyNamingStrategy(Map<String, Object> properties, String key,
......
...@@ -33,6 +33,8 @@ import javax.transaction.TransactionManager; ...@@ -33,6 +33,8 @@ import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction; import javax.transaction.UserTransaction;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform; import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.junit.Test; import org.junit.Test;
...@@ -47,7 +49,10 @@ import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfigurati ...@@ -47,7 +49,10 @@ import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfigurati
import org.springframework.boot.autoconfigure.orm.jpa.mapping.NonAnnotatedEntity; import org.springframework.boot.autoconfigure.orm.jpa.mapping.NonAnnotatedEntity;
import org.springframework.boot.autoconfigure.orm.jpa.test.City; import org.springframework.boot.autoconfigure.orm.jpa.test.City;
import org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration; import org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration;
import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy;
import org.springframework.boot.orm.jpa.hibernate.SpringJtaPlatform; import org.springframework.boot.orm.jpa.hibernate.SpringJtaPlatform;
import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
...@@ -268,6 +273,83 @@ public class HibernateJpaAutoConfigurationTests ...@@ -268,6 +273,83 @@ public class HibernateJpaAutoConfigurationTests
}); });
} }
@Test
public void physicalNamingStrategyCanBeUsed() {
contextRunner()
.withUserConfiguration(TestPhysicalNamingStrategyConfiguration.class)
.run((context) -> {
Map<String, Object> hibernateProperties = context.getBean(
HibernateJpaConfiguration.class).getVendorProperties();
assertThat(hibernateProperties).contains(
entry("hibernate.physical_naming_strategy",
context.getBean("testPhysicalNamingStrategy")));
assertThat(hibernateProperties)
.doesNotContainKeys("hibernate.ejb.naming_strategy");
});
}
@Test
public void implicitNamingStrategyCanBeUsed() {
contextRunner()
.withUserConfiguration(TestImplicitNamingStrategyConfiguration.class)
.run((context) -> {
Map<String, Object> hibernateProperties = context.getBean(
HibernateJpaConfiguration.class).getVendorProperties();
assertThat(hibernateProperties).contains(
entry("hibernate.implicit_naming_strategy",
context.getBean("testImplicitNamingStrategy")));
assertThat(hibernateProperties)
.doesNotContainKeys("hibernate.ejb.naming_strategy");
});
}
@Test
public void namingStrategyInstancesTakePrecedenceOverNamingStrategyProperties() {
contextRunner()
.withUserConfiguration(TestPhysicalNamingStrategyConfiguration.class,
TestImplicitNamingStrategyConfiguration.class)
.withPropertyValues(
"spring.jpa.hibernate.naming.physical-strategy:com.example.Physical",
"spring.jpa.hibernate.naming.implicit-strategy:com.example.Implicit")
.run((context) -> {
Map<String, Object> hibernateProperties = context.getBean(
HibernateJpaConfiguration.class).getVendorProperties();
assertThat(hibernateProperties).contains(
entry("hibernate.physical_naming_strategy",
context.getBean("testPhysicalNamingStrategy")),
entry("hibernate.implicit_naming_strategy",
context.getBean("testImplicitNamingStrategy")));
assertThat(hibernateProperties)
.doesNotContainKeys("hibernate.ejb.naming_strategy");
});
}
@Test
public void hibernatePropertiesCustomizerTakePrecedenceOverStrategyInstancesAndNamingStrategyProperties() {
contextRunner()
.withUserConfiguration(
TestHibernatePropertiesCustomizerConfiguration.class,
TestPhysicalNamingStrategyConfiguration.class,
TestImplicitNamingStrategyConfiguration.class)
.withPropertyValues(
"spring.jpa.hibernate.naming.physical-strategy:com.example.Physical",
"spring.jpa.hibernate.naming.implicit-strategy:com.example.Implicit")
.run((context) -> {
Map<String, Object> hibernateProperties = context.getBean(
HibernateJpaConfiguration.class).getVendorProperties();
TestHibernatePropertiesCustomizerConfiguration configuration = context.getBean(
TestHibernatePropertiesCustomizerConfiguration.class);
assertThat(hibernateProperties).contains(
entry("hibernate.physical_naming_strategy",
configuration.physicalNamingStrategy),
entry("hibernate.implicit_naming_strategy",
configuration.implicitNamingStrategy));
assertThat(hibernateProperties)
.doesNotContainKeys("hibernate.ejb.naming_strategy");
});
}
@Configuration @Configuration
@TestAutoConfigurationPackage(City.class) @TestAutoConfigurationPackage(City.class)
static class TestInitializedJpaConfiguration { static class TestInitializedJpaConfiguration {
...@@ -288,6 +370,45 @@ public class HibernateJpaAutoConfigurationTests ...@@ -288,6 +370,45 @@ public class HibernateJpaAutoConfigurationTests
} }
@Configuration
static class TestImplicitNamingStrategyConfiguration {
@Bean
public ImplicitNamingStrategy testImplicitNamingStrategy() {
return new SpringImplicitNamingStrategy();
}
}
@Configuration
static class TestPhysicalNamingStrategyConfiguration {
@Bean
public PhysicalNamingStrategy testPhysicalNamingStrategy() {
return new SpringPhysicalNamingStrategy();
}
}
@Configuration
static class TestHibernatePropertiesCustomizerConfiguration {
private final PhysicalNamingStrategy physicalNamingStrategy = new SpringPhysicalNamingStrategy();
private final ImplicitNamingStrategy implicitNamingStrategy = new SpringImplicitNamingStrategy();
@Bean
public HibernatePropertiesCustomizer testHibernatePropertiesCustomizer() {
return (hibernateProperties) -> {
hibernateProperties.put("hibernate.physical_naming_strategy",
this.physicalNamingStrategy);
hibernateProperties.put("hibernate.implicit_naming_strategy",
this.implicitNamingStrategy);
};
}
}
public static class TestJtaPlatform implements JtaPlatform { public static class TestJtaPlatform implements JtaPlatform {
@Override @Override
......
...@@ -19,15 +19,12 @@ package org.springframework.boot.autoconfigure.orm.jpa; ...@@ -19,15 +19,12 @@ package org.springframework.boot.autoconfigure.orm.jpa;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DatabaseMetaData; import java.sql.DatabaseMetaData;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier; import java.util.function.Supplier;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
...@@ -102,81 +99,6 @@ public class JpaPropertiesTests { ...@@ -102,81 +99,6 @@ public class JpaPropertiesTests {
})); }));
} }
@Test
public void namingStrategyInstancesCanBeUsed() {
this.contextRunner.run(assertJpaProperties((properties) -> {
ImplicitNamingStrategy implicitStrategy = mock(ImplicitNamingStrategy.class);
PhysicalNamingStrategy physicalStrategy = mock(PhysicalNamingStrategy.class);
Map<String, Object> hibernateProperties = properties.getHibernateProperties(
new HibernateSettings().implicitNamingStrategy(implicitStrategy)
.physicalNamingStrategy(physicalStrategy));
assertThat(hibernateProperties).contains(
entry("hibernate.implicit_naming_strategy", implicitStrategy),
entry("hibernate.physical_naming_strategy", physicalStrategy));
assertThat(hibernateProperties)
.doesNotContainKeys("hibernate.ejb.naming_strategy");
}));
}
@Test
public void namingStrategyInstancesTakePrecedenceOverNamingStrategyProperties() {
this.contextRunner.withPropertyValues(
"spring.jpa.hibernate.naming.implicit-strategy:com.example.Implicit",
"spring.jpa.hibernate.naming.physical-strategy:com.example.Physical")
.run(assertJpaProperties((properties) -> {
ImplicitNamingStrategy implicitStrategy = mock(
ImplicitNamingStrategy.class);
PhysicalNamingStrategy physicalStrategy = mock(
PhysicalNamingStrategy.class);
Map<String, Object> hibernateProperties = properties
.getHibernateProperties(new HibernateSettings()
.implicitNamingStrategy(implicitStrategy)
.physicalNamingStrategy(physicalStrategy));
assertThat(hibernateProperties).contains(
entry("hibernate.implicit_naming_strategy", implicitStrategy),
entry("hibernate.physical_naming_strategy",
physicalStrategy));
assertThat(hibernateProperties)
.doesNotContainKeys("hibernate.ejb.naming_strategy");
}));
}
@Test
public void hibernatePropertiesCustomizerTakePrecedenceOverStrategyInstancesAndNamingStrategyProperties() {
this.contextRunner.withPropertyValues(
"spring.jpa.hibernate.naming.implicit-strategy:com.example.Implicit",
"spring.jpa.hibernate.naming.physical-strategy:com.example.Physical")
.run(assertJpaProperties((properties) -> {
ImplicitNamingStrategy implicitStrategy = mock(
ImplicitNamingStrategy.class);
PhysicalNamingStrategy physicalStrategy = mock(
PhysicalNamingStrategy.class);
ImplicitNamingStrategy effectiveImplicitStrategy = mock(
ImplicitNamingStrategy.class);
PhysicalNamingStrategy effectivePhysicalStrategy = mock(
PhysicalNamingStrategy.class);
HibernatePropertiesCustomizer customizer = (hibernateProperties) -> {
hibernateProperties.put("hibernate.implicit_naming_strategy",
effectiveImplicitStrategy);
hibernateProperties.put("hibernate.physical_naming_strategy",
effectivePhysicalStrategy);
};
Map<String, Object> hibernateProperties = properties
.getHibernateProperties(new HibernateSettings()
.implicitNamingStrategy(implicitStrategy)
.physicalNamingStrategy(physicalStrategy)
.hibernatePropertiesCustomizers(
Collections.singleton(customizer)));
assertThat(hibernateProperties).contains(
entry("hibernate.implicit_naming_strategy",
effectiveImplicitStrategy),
entry("hibernate.physical_naming_strategy",
effectivePhysicalStrategy));
assertThat(hibernateProperties)
.doesNotContainKeys("hibernate.ejb.naming_strategy");
}));
}
@Test @Test
public void hibernate5CustomNamingStrategiesViaJpaProperties() { public void hibernate5CustomNamingStrategiesViaJpaProperties() {
this.contextRunner.withPropertyValues( this.contextRunner.withPropertyValues(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment