Merge pull request #46213 from quaff

* pr/46213:
  Polish 'Introduce a shared abstraction for database initialization'
  Introduce a shared abstraction for database initialization

Closes gh-46213
This commit is contained in:
Phillip Webb
2025-10-22 13:37:57 -07:00
15 changed files with 269 additions and 351 deletions
@@ -16,14 +16,11 @@
package org.springframework.boot.batch.jdbc.autoconfigure;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer;
import org.springframework.boot.jdbc.init.PlatformPlaceholderDatabaseDriverResolver;
import org.springframework.boot.jdbc.init.PropertiesBasedDataSourceScriptDatabaseInitializer;
import org.springframework.boot.sql.init.DatabaseInitializationSettings;
import org.springframework.util.StringUtils;
/**
* {@link DataSourceScriptDatabaseInitializer} for the Spring Batch database. May be
@@ -33,53 +30,24 @@ import org.springframework.util.StringUtils;
* @author Vedran Pavic
* @author Andy Wilkinson
* @author Phillip Webb
* @author Yanming Zhou
* @since 4.0.0
*/
public class BatchDataSourceScriptDatabaseInitializer extends DataSourceScriptDatabaseInitializer {
public class BatchDataSourceScriptDatabaseInitializer
extends PropertiesBasedDataSourceScriptDatabaseInitializer<BatchJdbcProperties> {
/**
* Create a new {@link BatchDataSourceScriptDatabaseInitializer} instance.
* @param dataSource the Spring Batch data source
* @param properties the Spring Batch JDBC properties
* @see #getSettings
*/
public BatchDataSourceScriptDatabaseInitializer(DataSource dataSource, BatchJdbcProperties properties) {
this(dataSource, getSettings(dataSource, properties));
super(dataSource, properties);
}
/**
* Create a new {@link BatchDataSourceScriptDatabaseInitializer} instance.
* @param dataSource the Spring Batch data source
* @param settings the database initialization settings
* @see #getSettings
*/
public BatchDataSourceScriptDatabaseInitializer(DataSource dataSource, DatabaseInitializationSettings settings) {
super(dataSource, settings);
}
/**
* Adapts {@link BatchJdbcProperties} to {@link DatabaseInitializationSettings}
* replacing any {@literal @@platform@@} placeholders.
* @param dataSource the Spring Batch data source
* @param properties batch JDBC properties
* @return a new {@link DatabaseInitializationSettings} instance
* @see #BatchDataSourceScriptDatabaseInitializer(DataSource,
* DatabaseInitializationSettings)
*/
public static DatabaseInitializationSettings getSettings(DataSource dataSource, BatchJdbcProperties properties) {
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
settings.setSchemaLocations(resolveSchemaLocations(dataSource, properties));
settings.setMode(properties.getInitializeSchema());
settings.setContinueOnError(true);
return settings;
}
private static List<String> resolveSchemaLocations(DataSource dataSource, BatchJdbcProperties properties) {
PlatformPlaceholderDatabaseDriverResolver platformResolver = new PlatformPlaceholderDatabaseDriverResolver();
if (StringUtils.hasText(properties.getPlatform())) {
return platformResolver.resolveAll(properties.getPlatform(), properties.getSchema());
}
return platformResolver.resolveAll(dataSource, properties.getSchema());
@Override
protected DatabaseInitializationSettings getSettings() {
return super.getSettings();
}
}
@@ -19,17 +19,18 @@ package org.springframework.boot.batch.jdbc.autoconfigure;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.sql.init.DatabaseInitializationMode;
import org.springframework.boot.jdbc.init.DatabaseInitializationProperties;
import org.springframework.transaction.annotation.Isolation;
/**
* Configuration properties for Spring Batch using a JDBC store.
*
* @author Stephane Nicoll
* @author Yanming Zhou
* @since 4.0.0
*/
@ConfigurationProperties("spring.batch.jdbc")
public class BatchJdbcProperties {
public class BatchJdbcProperties extends DatabaseInitializationProperties {
private static final String DEFAULT_SCHEMA_LOCATION = "classpath:org/springframework/"
+ "batch/core/schema-@@platform@@.sql";
@@ -44,27 +45,11 @@ public class BatchJdbcProperties {
*/
private @Nullable Isolation isolationLevelForCreate;
/**
* Path to the SQL file to use to initialize the database schema.
*/
private String schema = DEFAULT_SCHEMA_LOCATION;
/**
* Platform to use in initialization scripts if the @@platform@@ placeholder is used.
* Auto-detected by default.
*/
private @Nullable String platform;
/**
* Table prefix for all the batch meta-data tables.
*/
private @Nullable String tablePrefix;
/**
* Database schema initialization mode.
*/
private DatabaseInitializationMode initializeSchema = DatabaseInitializationMode.EMBEDDED;
public boolean isValidateTransactionState() {
return this.validateTransactionState;
}
@@ -81,22 +66,6 @@ public class BatchJdbcProperties {
this.isolationLevelForCreate = isolationLevelForCreate;
}
public String getSchema() {
return this.schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
public @Nullable String getPlatform() {
return this.platform;
}
public void setPlatform(@Nullable String platform) {
this.platform = platform;
}
public @Nullable String getTablePrefix() {
return this.tablePrefix;
}
@@ -105,12 +74,9 @@ public class BatchJdbcProperties {
this.tablePrefix = tablePrefix;
}
public DatabaseInitializationMode getInitializeSchema() {
return this.initializeSchema;
}
public void setInitializeSchema(DatabaseInitializationMode initializeSchema) {
this.initializeSchema = initializeSchema;
@Override
public String getDefaultSchemaLocation() {
return DEFAULT_SCHEMA_LOCATION;
}
}
@@ -54,8 +54,8 @@ class BatchDataSourceScriptDatabaseInitializerTests {
DataSource dataSource = mock(DataSource.class);
BatchJdbcProperties properties = new BatchJdbcProperties();
properties.setPlatform("test");
DatabaseInitializationSettings settings = BatchDataSourceScriptDatabaseInitializer.getSettings(dataSource,
properties);
DatabaseInitializationSettings settings = new BatchDataSourceScriptDatabaseInitializer(dataSource, properties)
.getSettings();
assertThat(settings.getSchemaLocations())
.containsOnly("classpath:org/springframework/batch/core/schema-test.sql");
then(dataSource).shouldHaveNoInteractions();
@@ -74,8 +74,8 @@ class BatchDataSourceScriptDatabaseInitializerTests {
given(connection.getMetaData()).willReturn(metadata);
String productName = (String) ReflectionTestUtils.getField(driver, "productName");
given(metadata.getDatabaseProductName()).willReturn(productName);
DatabaseInitializationSettings settings = BatchDataSourceScriptDatabaseInitializer.getSettings(dataSource,
properties);
DatabaseInitializationSettings settings = new BatchDataSourceScriptDatabaseInitializer(dataSource, properties)
.getSettings();
List<String> schemaLocations = settings.getSchemaLocations();
assertThat(schemaLocations).isNotEmpty()
.allSatisfy((location) -> assertThat(resourceLoader.getResource(location).exists()).isTrue());
@@ -16,15 +16,14 @@
package org.springframework.boot.integration.autoconfigure;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer;
import org.springframework.boot.jdbc.init.PlatformPlaceholderDatabaseDriverResolver;
import org.springframework.boot.jdbc.init.PropertiesBasedDataSourceScriptDatabaseInitializer;
import org.springframework.boot.sql.init.DatabaseInitializationSettings;
import org.springframework.util.StringUtils;
/**
* {@link DataSourceScriptDatabaseInitializer} for the Spring Integration database. May be
@@ -32,9 +31,11 @@ import org.springframework.util.StringUtils;
*
* @author Vedran Pavic
* @author Andy Wilkinson
* @author Yanming Zhou
* @since 4.0.0
*/
public class IntegrationDataSourceScriptDatabaseInitializer extends DataSourceScriptDatabaseInitializer {
public class IntegrationDataSourceScriptDatabaseInitializer
extends PropertiesBasedDataSourceScriptDatabaseInitializer<IntegrationJdbcProperties> {
/**
* Create a new {@link IntegrationDataSourceScriptDatabaseInitializer} instance.
@@ -43,45 +44,12 @@ public class IntegrationDataSourceScriptDatabaseInitializer extends DataSourceSc
* @see #getSettings
*/
public IntegrationDataSourceScriptDatabaseInitializer(DataSource dataSource, IntegrationJdbcProperties properties) {
this(dataSource, getSettings(dataSource, properties));
super(dataSource, properties, Map.of(DatabaseDriver.MARIADB, "mysql"));
}
/**
* Create a new {@link IntegrationDataSourceScriptDatabaseInitializer} instance.
* @param dataSource the Spring Integration data source
* @param settings the database initialization settings
* @see #getSettings
*/
public IntegrationDataSourceScriptDatabaseInitializer(DataSource dataSource,
DatabaseInitializationSettings settings) {
super(dataSource, settings);
}
/**
* Adapts {@link IntegrationJdbcProperties Spring Integration JDBC properties} to
* {@link DatabaseInitializationSettings} replacing any {@literal @@platform@@}
* placeholders.
* @param dataSource the Spring Integration data source
* @param properties the Spring Integration JDBC properties
* @return a new {@link DatabaseInitializationSettings} instance
* @see #IntegrationDataSourceScriptDatabaseInitializer(DataSource,
* DatabaseInitializationSettings)
*/
static DatabaseInitializationSettings getSettings(DataSource dataSource, IntegrationJdbcProperties properties) {
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
settings.setSchemaLocations(resolveSchemaLocations(dataSource, properties));
settings.setMode(properties.getInitializeSchema());
settings.setContinueOnError(true);
return settings;
}
private static List<String> resolveSchemaLocations(DataSource dataSource, IntegrationJdbcProperties properties) {
PlatformPlaceholderDatabaseDriverResolver platformResolver = new PlatformPlaceholderDatabaseDriverResolver();
platformResolver = platformResolver.withDriverPlatform(DatabaseDriver.MARIADB, "mysql");
if (StringUtils.hasText(properties.getPlatform())) {
return platformResolver.resolveAll(properties.getPlatform(), properties.getSchema());
}
return platformResolver.resolveAll(dataSource, properties.getSchema());
@Override
protected DatabaseInitializationSettings getSettings() {
return super.getSettings();
}
}
@@ -16,10 +16,8 @@
package org.springframework.boot.integration.autoconfigure;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.sql.init.DatabaseInitializationMode;
import org.springframework.boot.jdbc.init.DatabaseInitializationProperties;
/**
* Configuration properties for Spring Integration JDBC.
@@ -27,52 +25,18 @@ import org.springframework.boot.sql.init.DatabaseInitializationMode;
* @author Vedran Pavic
* @author Stephane Nicoll
* @author Artem Bilan
* @author Yanming Zhou
* @since 4.0.0
*/
@ConfigurationProperties("spring.integration.jdbc")
public class IntegrationJdbcProperties {
public class IntegrationJdbcProperties extends DatabaseInitializationProperties {
private static final String DEFAULT_SCHEMA_LOCATION = "classpath:org/springframework/"
+ "integration/jdbc/schema-@@platform@@.sql";
/**
* Path to the SQL file to use to initialize the database schema.
*/
private String schema = DEFAULT_SCHEMA_LOCATION;
/**
* Platform to use in initialization scripts if the @@platform@@ placeholder is used.
* Auto-detected by default.
*/
private @Nullable String platform;
/**
* Database schema initialization mode.
*/
private DatabaseInitializationMode initializeSchema = DatabaseInitializationMode.EMBEDDED;
public String getSchema() {
return this.schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
public @Nullable String getPlatform() {
return this.platform;
}
public void setPlatform(@Nullable String platform) {
this.platform = platform;
}
public DatabaseInitializationMode getInitializeSchema() {
return this.initializeSchema;
}
public void setInitializeSchema(DatabaseInitializationMode initializeSchema) {
this.initializeSchema = initializeSchema;
@Override
public String getDefaultSchemaLocation() {
return DEFAULT_SCHEMA_LOCATION;
}
}
@@ -38,8 +38,9 @@ class IntegrationDataSourceScriptDatabaseInitializerTests {
DataSource dataSource = mock(DataSource.class);
IntegrationJdbcProperties properties = new IntegrationJdbcProperties();
properties.setPlatform("test");
DatabaseInitializationSettings settings = IntegrationDataSourceScriptDatabaseInitializer.getSettings(dataSource,
properties);
DatabaseInitializationSettings settings = new IntegrationDataSourceScriptDatabaseInitializer(dataSource,
properties)
.getSettings();
assertThat(settings.getSchemaLocations())
.containsOnly("classpath:org/springframework/integration/jdbc/schema-test.sql");
then(dataSource).shouldHaveNoInteractions();
@@ -0,0 +1,89 @@
/*
* Copyright 2012-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.jdbc.init;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.ConfigurationPropertiesSource;
import org.springframework.boot.sql.init.DatabaseInitializationMode;
/**
* Base configuration properties class for performing SQL database initialization.
*
* @author Yanming Zhou
* @since 4.0.0
*/
@ConfigurationPropertiesSource
public abstract class DatabaseInitializationProperties {
/**
* Path to the SQL file to use to initialize the database schema.
*/
private String schema = getDefaultSchemaLocation();
/**
* Platform to use in initialization scripts if the @@platform@@ placeholder is used.
* Auto-detected by default.
*/
private @Nullable String platform;
/**
* Database schema initialization mode.
*/
private DatabaseInitializationMode initializeSchema = DatabaseInitializationMode.EMBEDDED;
/**
* Whether initialization should continue when an error occurs when applying a schema
* script.
*/
private boolean continueOnError = true;
public String getSchema() {
return this.schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
public @Nullable String getPlatform() {
return this.platform;
}
public void setPlatform(String platform) {
this.platform = platform;
}
public DatabaseInitializationMode getInitializeSchema() {
return this.initializeSchema;
}
public void setInitializeSchema(DatabaseInitializationMode initializeSchema) {
this.initializeSchema = initializeSchema;
}
public boolean isContinueOnError() {
return this.continueOnError;
}
public void setContinueOnError(boolean continueOnError) {
this.continueOnError = continueOnError;
}
public abstract String getDefaultSchemaLocation();
}
@@ -0,0 +1,93 @@
/*
* Copyright 2012-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.jdbc.init;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.boot.sql.init.DatabaseInitializationSettings;
import org.springframework.util.StringUtils;
/**
* Convenience class for construct {@link DataSourceScriptDatabaseInitializer} base on
* {@link DatabaseInitializationProperties}.
*
* @param <T> the {@link DatabaseInitializationProperties} type being used
* @author Yanming Zhou
* @since 4.0.0
*/
public class PropertiesBasedDataSourceScriptDatabaseInitializer<T extends DatabaseInitializationProperties>
extends DataSourceScriptDatabaseInitializer {
/**
* Create a new {@link PropertiesBasedDataSourceScriptDatabaseInitializer} instance.
* @param dataSource the data source
* @param properties the configuration properties
* @see #getSettings
*/
public PropertiesBasedDataSourceScriptDatabaseInitializer(DataSource dataSource, T properties) {
this(dataSource, properties, Collections.emptyMap());
}
/**
* Create a new {@link PropertiesBasedDataSourceScriptDatabaseInitializer} instance.
* @param dataSource the data source
* @param properties the configuration properties
* @param driverMappings the driver mappings
* @see #getSettings
*/
public PropertiesBasedDataSourceScriptDatabaseInitializer(DataSource dataSource, T properties,
Map<DatabaseDriver, String> driverMappings) {
super(dataSource, getSettings(dataSource, properties, driverMappings));
}
/**
* Adapts {@link DatabaseInitializationProperties configuration properties} to
* {@link DatabaseInitializationSettings} replacing any {@literal @@platform@@}
* placeholders.
* @param dataSource the data source
* @param properties the configuration properties
* @param driverMappings the driver mappings
* @param <T> the {@link DatabaseInitializationProperties} type being used
* @return a new {@link DatabaseInitializationSettings} instance
*/
private static <T extends DatabaseInitializationProperties> DatabaseInitializationSettings getSettings(
DataSource dataSource, T properties, Map<DatabaseDriver, String> driverMappings) {
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
settings.setSchemaLocations(resolveSchemaLocations(dataSource, properties, driverMappings));
settings.setMode(properties.getInitializeSchema());
settings.setContinueOnError(properties.isContinueOnError());
return settings;
}
private static <T extends DatabaseInitializationProperties> List<String> resolveSchemaLocations(
DataSource dataSource, T properties, Map<DatabaseDriver, String> driverMappings) {
PlatformPlaceholderDatabaseDriverResolver platformResolver = new PlatformPlaceholderDatabaseDriverResolver();
for (Map.Entry<DatabaseDriver, String> entry : driverMappings.entrySet()) {
platformResolver = platformResolver.withDriverPlatform(entry.getKey(), entry.getValue());
}
if (StringUtils.hasText(properties.getPlatform())) {
return platformResolver.resolveAll(properties.getPlatform(), properties.getSchema());
}
return platformResolver.resolveAll(dataSource, properties.getSchema());
}
}
@@ -17,6 +17,7 @@
package org.springframework.boot.quartz.autoconfigure;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
@@ -24,11 +25,10 @@ import org.jspecify.annotations.Nullable;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer;
import org.springframework.boot.jdbc.init.PlatformPlaceholderDatabaseDriverResolver;
import org.springframework.boot.jdbc.init.PropertiesBasedDataSourceScriptDatabaseInitializer;
import org.springframework.boot.sql.init.DatabaseInitializationSettings;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
* {@link DataSourceScriptDatabaseInitializer} for the Quartz Scheduler database. May be
@@ -37,9 +37,11 @@ import org.springframework.util.StringUtils;
* @author Vedran Pavic
* @author Andy Wilkinson
* @author Phillip Webb
* @author Yanming Zhou
* @since 4.0.0
*/
public class QuartzDataSourceScriptDatabaseInitializer extends DataSourceScriptDatabaseInitializer {
public class QuartzDataSourceScriptDatabaseInitializer
extends PropertiesBasedDataSourceScriptDatabaseInitializer<QuartzJdbcProperties> {
private final @Nullable List<String> commentPrefixes;
@@ -50,23 +52,15 @@ public class QuartzDataSourceScriptDatabaseInitializer extends DataSourceScriptD
* @see #getSettings
*/
public QuartzDataSourceScriptDatabaseInitializer(DataSource dataSource, QuartzJdbcProperties properties) {
this(dataSource, getSettings(dataSource, properties), properties.getCommentPrefix());
super(dataSource, properties,
Map.of(DatabaseDriver.DB2, "db2_v95", DatabaseDriver.MYSQL, "mysql_innodb", DatabaseDriver.MARIADB,
"mysql_innodb", DatabaseDriver.POSTGRESQL, "postgres", DatabaseDriver.SQLSERVER, "sqlServer"));
this.commentPrefixes = properties.getCommentPrefix();
}
/**
* Create a new {@link QuartzDataSourceScriptDatabaseInitializer} instance.
* @param dataSource the Quartz Scheduler data source
* @param settings the database initialization settings
* @see #getSettings
*/
public QuartzDataSourceScriptDatabaseInitializer(DataSource dataSource, DatabaseInitializationSettings settings) {
this(dataSource, settings, null);
}
private QuartzDataSourceScriptDatabaseInitializer(DataSource dataSource, DatabaseInitializationSettings settings,
@Nullable List<String> commentPrefixes) {
super(dataSource, settings);
this.commentPrefixes = commentPrefixes;
@Override
protected DatabaseInitializationSettings getSettings() {
return super.getSettings();
}
@Override
@@ -76,35 +70,4 @@ public class QuartzDataSourceScriptDatabaseInitializer extends DataSourceScriptD
}
}
/**
* Adapts {@link QuartzProperties Quartz properties} to
* {@link DatabaseInitializationSettings} replacing any {@literal @@platform@@}
* placeholders.
* @param dataSource the Quartz Scheduler data source
* @param properties the Quartz properties
* @return a new {@link DatabaseInitializationSettings} instance
* @see #QuartzDataSourceScriptDatabaseInitializer(DataSource,
* DatabaseInitializationSettings)
*/
public static DatabaseInitializationSettings getSettings(DataSource dataSource, QuartzJdbcProperties properties) {
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
settings.setSchemaLocations(resolveSchemaLocations(dataSource, properties));
settings.setMode(properties.getInitializeSchema());
settings.setContinueOnError(true);
return settings;
}
private static List<String> resolveSchemaLocations(DataSource dataSource, QuartzJdbcProperties properties) {
PlatformPlaceholderDatabaseDriverResolver platformResolver = new PlatformPlaceholderDatabaseDriverResolver();
platformResolver = platformResolver.withDriverPlatform(DatabaseDriver.DB2, "db2_v95");
platformResolver = platformResolver.withDriverPlatform(DatabaseDriver.MYSQL, "mysql_innodb");
platformResolver = platformResolver.withDriverPlatform(DatabaseDriver.MARIADB, "mysql_innodb");
platformResolver = platformResolver.withDriverPlatform(DatabaseDriver.POSTGRESQL, "postgres");
platformResolver = platformResolver.withDriverPlatform(DatabaseDriver.SQLSERVER, "sqlServer");
if (StringUtils.hasText(properties.getPlatform())) {
return platformResolver.resolveAll(properties.getPlatform(), properties.getSchema());
}
return platformResolver.resolveAll(dataSource, properties.getSchema());
}
}
@@ -20,10 +20,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.sql.init.DatabaseInitializationMode;
import org.springframework.boot.jdbc.init.DatabaseInitializationProperties;
/**
* Configuration properties for the Quartz Scheduler integration when using a JDBC job
@@ -31,59 +29,20 @@ import org.springframework.boot.sql.init.DatabaseInitializationMode;
*
* @author Vedran Pavic
* @author Stephane Nicoll
* @author Yanming Zhou
* @since 4.0.0
*/
@ConfigurationProperties("spring.quartz.jdbc")
public class QuartzJdbcProperties {
public class QuartzJdbcProperties extends DatabaseInitializationProperties {
private static final String DEFAULT_SCHEMA_LOCATION = "classpath:org/quartz/impl/"
+ "jdbcjobstore/tables_@@platform@@.sql";
/**
* Path to the SQL file to use to initialize the database schema.
*/
private String schema = DEFAULT_SCHEMA_LOCATION;
/**
* Platform to use in initialization scripts if the @@platform@@ placeholder is used.
* Auto-detected by default.
*/
private @Nullable String platform;
/**
* Database schema initialization mode.
*/
private DatabaseInitializationMode initializeSchema = DatabaseInitializationMode.EMBEDDED;
/**
* Prefixes for single-line comments in SQL initialization scripts.
*/
private List<String> commentPrefix = new ArrayList<>(Arrays.asList("#", "--"));
public String getSchema() {
return this.schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
public @Nullable String getPlatform() {
return this.platform;
}
public void setPlatform(@Nullable String platform) {
this.platform = platform;
}
public DatabaseInitializationMode getInitializeSchema() {
return this.initializeSchema;
}
public void setInitializeSchema(DatabaseInitializationMode initializeSchema) {
this.initializeSchema = initializeSchema;
}
public List<String> getCommentPrefix() {
return this.commentPrefix;
}
@@ -92,4 +51,9 @@ public class QuartzJdbcProperties {
this.commentPrefix = commentPrefix;
}
@Override
public String getDefaultSchemaLocation() {
return DEFAULT_SCHEMA_LOCATION;
}
}
@@ -41,8 +41,8 @@ class QuartzDataSourceScriptDatabaseInitializerTests {
DataSource dataSource = mock(DataSource.class);
QuartzJdbcProperties properties = new QuartzJdbcProperties();
properties.setPlatform("test");
DatabaseInitializationSettings settings = QuartzDataSourceScriptDatabaseInitializer.getSettings(dataSource,
properties);
DatabaseInitializationSettings settings = new QuartzDataSourceScriptDatabaseInitializer(dataSource, properties)
.getSettings();
assertThat(settings.getSchemaLocations())
.containsOnly("classpath:org/quartz/impl/jdbcjobstore/tables_test.sql");
then(dataSource).shouldHaveNoInteractions();
@@ -16,15 +16,14 @@
package org.springframework.boot.session.jdbc.autoconfigure;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer;
import org.springframework.boot.jdbc.init.PlatformPlaceholderDatabaseDriverResolver;
import org.springframework.boot.jdbc.init.PropertiesBasedDataSourceScriptDatabaseInitializer;
import org.springframework.boot.sql.init.DatabaseInitializationSettings;
import org.springframework.util.StringUtils;
/**
* {@link DataSourceScriptDatabaseInitializer} for the Spring Session JDBC database. May
@@ -34,9 +33,11 @@ import org.springframework.util.StringUtils;
* @author Vedran Pavic
* @author Andy Wilkinson
* @author Phillip Webb
* @author Yanming Zhou
* @since 4.0.0
*/
public class JdbcSessionDataSourceScriptDatabaseInitializer extends DataSourceScriptDatabaseInitializer {
public class JdbcSessionDataSourceScriptDatabaseInitializer
extends PropertiesBasedDataSourceScriptDatabaseInitializer<JdbcSessionProperties> {
/**
* Create a new {@link JdbcSessionDataSourceScriptDatabaseInitializer} instance.
@@ -45,45 +46,12 @@ public class JdbcSessionDataSourceScriptDatabaseInitializer extends DataSourceSc
* @see #getSettings
*/
public JdbcSessionDataSourceScriptDatabaseInitializer(DataSource dataSource, JdbcSessionProperties properties) {
this(dataSource, getSettings(dataSource, properties));
super(dataSource, properties, Map.of(DatabaseDriver.MARIADB, "mysql"));
}
/**
* Create a new {@link JdbcSessionDataSourceScriptDatabaseInitializer} instance.
* @param dataSource the Spring Session JDBC data source
* @param settings the database initialization settings
* @see #getSettings
*/
public JdbcSessionDataSourceScriptDatabaseInitializer(DataSource dataSource,
DatabaseInitializationSettings settings) {
super(dataSource, settings);
}
/**
* Adapts {@link JdbcSessionProperties Spring Session JDBC properties} to
* {@link DatabaseInitializationSettings} replacing any {@literal @@platform@@}
* placeholders.
* @param dataSource the Spring Session JDBC data source
* @param properties the Spring Session JDBC properties
* @return a new {@link DatabaseInitializationSettings} instance
* @see #JdbcSessionDataSourceScriptDatabaseInitializer(DataSource,
* DatabaseInitializationSettings)
*/
static DatabaseInitializationSettings getSettings(DataSource dataSource, JdbcSessionProperties properties) {
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
settings.setSchemaLocations(resolveSchemaLocations(dataSource, properties));
settings.setMode(properties.getInitializeSchema());
settings.setContinueOnError(true);
return settings;
}
private static List<String> resolveSchemaLocations(DataSource dataSource, JdbcSessionProperties properties) {
PlatformPlaceholderDatabaseDriverResolver platformResolver = new PlatformPlaceholderDatabaseDriverResolver();
platformResolver = platformResolver.withDriverPlatform(DatabaseDriver.MARIADB, "mysql");
if (StringUtils.hasText(properties.getPlatform())) {
return platformResolver.resolveAll(properties.getPlatform(), properties.getSchema());
}
return platformResolver.resolveAll(dataSource, properties.getSchema());
@Override
protected DatabaseInitializationSettings getSettings() {
return super.getSettings();
}
}
@@ -16,10 +16,8 @@
package org.springframework.boot.session.jdbc.autoconfigure;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.sql.init.DatabaseInitializationMode;
import org.springframework.boot.jdbc.init.DatabaseInitializationProperties;
import org.springframework.session.FlushMode;
import org.springframework.session.SaveMode;
@@ -27,10 +25,11 @@ import org.springframework.session.SaveMode;
* Configuration properties for JDBC-backed Spring Session.
*
* @author Vedran Pavic
* @author Yanming Zhou
* @since 4.0.0
*/
@ConfigurationProperties("spring.session.jdbc")
public class JdbcSessionProperties {
public class JdbcSessionProperties extends DatabaseInitializationProperties {
private static final String DEFAULT_SCHEMA_LOCATION = "classpath:org/springframework/"
+ "session/jdbc/schema-@@platform@@.sql";
@@ -39,17 +38,6 @@ public class JdbcSessionProperties {
private static final String DEFAULT_CLEANUP_CRON = "0 * * * * *";
/**
* Path to the SQL file to use to initialize the database schema.
*/
private String schema = DEFAULT_SCHEMA_LOCATION;
/**
* Platform to use in initialization scripts if the @@platform@@ placeholder is used.
* Auto-detected by default.
*/
private @Nullable String platform;
/**
* Name of the database table used to store sessions.
*/
@@ -60,11 +48,6 @@ public class JdbcSessionProperties {
*/
private String cleanupCron = DEFAULT_CLEANUP_CRON;
/**
* Database schema initialization mode.
*/
private DatabaseInitializationMode initializeSchema = DatabaseInitializationMode.EMBEDDED;
/**
* Sessions flush mode. Determines when session changes are written to the session
* store.
@@ -77,22 +60,6 @@ public class JdbcSessionProperties {
*/
private SaveMode saveMode = SaveMode.ON_SET_ATTRIBUTE;
public String getSchema() {
return this.schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
public @Nullable String getPlatform() {
return this.platform;
}
public void setPlatform(@Nullable String platform) {
this.platform = platform;
}
public String getTableName() {
return this.tableName;
}
@@ -109,14 +76,6 @@ public class JdbcSessionProperties {
this.cleanupCron = cleanupCron;
}
public DatabaseInitializationMode getInitializeSchema() {
return this.initializeSchema;
}
public void setInitializeSchema(DatabaseInitializationMode initializeSchema) {
this.initializeSchema = initializeSchema;
}
public FlushMode getFlushMode() {
return this.flushMode;
}
@@ -133,4 +92,9 @@ public class JdbcSessionProperties {
this.saveMode = saveMode;
}
@Override
public String getDefaultSchemaLocation() {
return DEFAULT_SCHEMA_LOCATION;
}
}
@@ -38,8 +38,9 @@ class JdbcSessionDataSourceScriptDatabaseInitializerTests {
DataSource dataSource = mock(DataSource.class);
JdbcSessionProperties properties = new JdbcSessionProperties();
properties.setPlatform("test");
DatabaseInitializationSettings settings = JdbcSessionDataSourceScriptDatabaseInitializer.getSettings(dataSource,
properties);
DatabaseInitializationSettings settings = new JdbcSessionDataSourceScriptDatabaseInitializer(dataSource,
properties)
.getSettings();
assertThat(settings.getSchemaLocations())
.containsOnly("classpath:org/springframework/session/jdbc/schema-test.sql");
then(dataSource).shouldHaveNoInteractions();
@@ -59,6 +59,15 @@ public abstract class AbstractScriptDatabaseInitializer implements ResourceLoade
this.settings = settings;
}
/**
* Return the {@link DatabaseInitializationSettings} being used by the initializer.
* @return the settings being used
* @since 4.0.0
*/
protected DatabaseInitializationSettings getSettings() {
return this.settings;
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;