Improve database initializers
This commit improves database initializers for Spring Batch and Spring Session by introducing `AbstractDatabaseInitializer` which eliminates duplicated logic in existing initializers. Additionally, database platform resolution now relies on `DatabaseDriver`. See gh-6543
This commit is contained in:
parent
d2d911ba94
commit
286a928347
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.autoconfigure;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.boot.jdbc.DatabaseDriver;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
|
||||
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
|
||||
import org.springframework.jdbc.support.JdbcUtils;
|
||||
import org.springframework.jdbc.support.MetaDataAccessException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Abstract base class for database schema initializers.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public abstract class AbstractDatabaseInitializer {
|
||||
|
||||
private static final String PLATFORM_PLACEHOLDER = "@@platform@@";
|
||||
|
||||
private DataSource dataSource;
|
||||
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
public AbstractDatabaseInitializer(DataSource dataSource, ResourceLoader resourceLoader) {
|
||||
Assert.notNull(dataSource, "DataSource must not be null");
|
||||
Assert.notNull(resourceLoader, "ResourceLoader must not be null");
|
||||
this.dataSource = dataSource;
|
||||
this.resourceLoader = resourceLoader;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
protected void initialize() {
|
||||
if (isEnabled()) {
|
||||
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
|
||||
String schemaLocation = getSchemaLocation();
|
||||
if (schemaLocation.contains(PLATFORM_PLACEHOLDER)) {
|
||||
String platform = customizeDatabaseName(getDatabaseName());
|
||||
schemaLocation = schemaLocation.replace(PLATFORM_PLACEHOLDER, platform);
|
||||
}
|
||||
populator.addScript(this.resourceLoader.getResource(schemaLocation));
|
||||
populator.setContinueOnError(true);
|
||||
DatabasePopulatorUtils.execute(populator, this.dataSource);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract boolean isEnabled();
|
||||
|
||||
protected abstract String getSchemaLocation();
|
||||
|
||||
protected String customizeDatabaseName(String databaseName) {
|
||||
return databaseName;
|
||||
}
|
||||
|
||||
private String getDatabaseName() {
|
||||
try {
|
||||
String databaseProductName = JdbcUtils.extractDatabaseMetaData(
|
||||
this.dataSource, "getDatabaseProductName").toString();
|
||||
databaseProductName = JdbcUtils.commonDatabaseName(databaseProductName);
|
||||
DatabaseDriver databaseDriver = DatabaseDriver.fromProductName(
|
||||
databaseProductName);
|
||||
if (databaseDriver == DatabaseDriver.UNKNOWN) {
|
||||
throw new IllegalStateException("Unable to detect database type");
|
||||
}
|
||||
return databaseDriver.toString().toLowerCase();
|
||||
}
|
||||
catch (MetaDataAccessException ex) {
|
||||
throw new IllegalStateException("Unable to detect database type", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -40,6 +40,7 @@ import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfigurat
|
|||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
|
@ -77,8 +78,9 @@ public class BatchAutoConfiguration {
|
|||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnBean(DataSource.class)
|
||||
public BatchDatabaseInitializer batchDatabaseInitializer() {
|
||||
return new BatchDatabaseInitializer();
|
||||
public BatchDatabaseInitializer batchDatabaseInitializer(DataSource dataSource,
|
||||
ResourceLoader resourceLoader) {
|
||||
return new BatchDatabaseInitializer(dataSource, resourceLoader, this.properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
|||
|
|
@ -16,63 +16,45 @@
|
|||
|
||||
package org.springframework.boot.autoconfigure.batch;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.batch.support.DatabaseType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.AbstractDatabaseInitializer;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
|
||||
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
|
||||
import org.springframework.jdbc.support.MetaDataAccessException;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Initialize the Spring Batch schema (ignoring errors, so should be idempotent).
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@Component
|
||||
public class BatchDatabaseInitializer {
|
||||
public class BatchDatabaseInitializer extends AbstractDatabaseInitializer {
|
||||
|
||||
@Autowired
|
||||
private BatchProperties properties;
|
||||
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
@Autowired
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
@PostConstruct
|
||||
protected void initialize() {
|
||||
if (this.properties.getInitializer().isEnabled()) {
|
||||
String platform = getDatabaseType();
|
||||
if ("hsql".equals(platform)) {
|
||||
platform = "hsqldb";
|
||||
}
|
||||
if ("postgres".equals(platform)) {
|
||||
platform = "postgresql";
|
||||
}
|
||||
if ("oracle".equals(platform)) {
|
||||
platform = "oracle10g";
|
||||
}
|
||||
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
|
||||
String schemaLocation = this.properties.getSchema();
|
||||
schemaLocation = schemaLocation.replace("@@platform@@", platform);
|
||||
populator.addScript(this.resourceLoader.getResource(schemaLocation));
|
||||
populator.setContinueOnError(true);
|
||||
DatabasePopulatorUtils.execute(populator, this.dataSource);
|
||||
}
|
||||
public BatchDatabaseInitializer(DataSource dataSource,
|
||||
ResourceLoader resourceLoader, BatchProperties properties) {
|
||||
super(dataSource, resourceLoader);
|
||||
Assert.notNull(properties, "BatchProperties must not be null");
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
private String getDatabaseType() {
|
||||
try {
|
||||
return DatabaseType.fromMetaData(this.dataSource).toString().toLowerCase();
|
||||
}
|
||||
catch (MetaDataAccessException ex) {
|
||||
throw new IllegalStateException("Unable to detect database type", ex);
|
||||
@Override
|
||||
protected boolean isEnabled() {
|
||||
return this.properties.getInitializer().isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSchemaLocation() {
|
||||
return this.properties.getSchema();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String customizeDatabaseName(String databaseName) {
|
||||
if ("oracle".equals(databaseName)) {
|
||||
return "oracle10g";
|
||||
}
|
||||
return databaseName;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,9 +47,9 @@ class JdbcSessionConfiguration {
|
|||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public JdbcSessionDatabaseInitializer jdbcSessionDatabaseInitializer(
|
||||
SessionProperties properties, DataSource dataSource,
|
||||
ResourceLoader resourceLoader) {
|
||||
return new JdbcSessionDatabaseInitializer(properties, dataSource, resourceLoader);
|
||||
DataSource dataSource, ResourceLoader resourceLoader,
|
||||
SessionProperties properties) {
|
||||
return new JdbcSessionDatabaseInitializer(dataSource, resourceLoader, properties);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
|
|
|||
|
|
@ -16,18 +16,10 @@
|
|||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AbstractDatabaseInitializer;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
|
||||
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
|
||||
import org.springframework.jdbc.support.JdbcUtils;
|
||||
import org.springframework.jdbc.support.MetaDataAccessException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
|
|
@ -36,64 +28,25 @@ import org.springframework.util.Assert;
|
|||
* @author Vedran Pavic
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public class JdbcSessionDatabaseInitializer {
|
||||
public class JdbcSessionDatabaseInitializer extends AbstractDatabaseInitializer {
|
||||
|
||||
private static Map<String, String> ALIASES;
|
||||
private SessionProperties.Jdbc properties;
|
||||
|
||||
static {
|
||||
Map<String, String> aliases = new HashMap<String, String>();
|
||||
aliases.put("apache derby", "derby");
|
||||
aliases.put("hsql database engine", "hsqldb");
|
||||
aliases.put("microsoft sql server", "sqlserver");
|
||||
ALIASES = Collections.unmodifiableMap(aliases);
|
||||
}
|
||||
|
||||
private SessionProperties properties;
|
||||
|
||||
private DataSource dataSource;
|
||||
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
public JdbcSessionDatabaseInitializer(SessionProperties properties,
|
||||
DataSource dataSource, ResourceLoader resourceLoader) {
|
||||
public JdbcSessionDatabaseInitializer(DataSource dataSource,
|
||||
ResourceLoader resourceLoader, SessionProperties properties) {
|
||||
super(dataSource, resourceLoader);
|
||||
Assert.notNull(properties, "SessionProperties must not be null");
|
||||
Assert.notNull(dataSource, "DataSource must not be null");
|
||||
Assert.notNull(resourceLoader, "ResourceLoader must not be null");
|
||||
this.properties = properties;
|
||||
this.dataSource = dataSource;
|
||||
this.resourceLoader = resourceLoader;
|
||||
this.properties = properties.getJdbc();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
protected void initialize() {
|
||||
if (this.properties.getJdbc().getInitializer().isEnabled()) {
|
||||
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
|
||||
String schemaLocation = this.properties.getJdbc().getSchema();
|
||||
schemaLocation = schemaLocation.replace("@@platform@@", getPlatform());
|
||||
populator.addScript(this.resourceLoader.getResource(schemaLocation));
|
||||
populator.setContinueOnError(true);
|
||||
DatabasePopulatorUtils.execute(populator, this.dataSource);
|
||||
}
|
||||
@Override
|
||||
protected boolean isEnabled() {
|
||||
return this.properties.getInitializer().isEnabled();
|
||||
}
|
||||
|
||||
private String getPlatform() {
|
||||
String databaseName = getDatabaseName();
|
||||
if (ALIASES.containsKey(databaseName)) {
|
||||
return ALIASES.get(databaseName);
|
||||
}
|
||||
return databaseName;
|
||||
}
|
||||
|
||||
private String getDatabaseName() {
|
||||
try {
|
||||
String databaseProductName = JdbcUtils
|
||||
.extractDatabaseMetaData(this.dataSource, "getDatabaseProductName")
|
||||
.toString();
|
||||
return JdbcUtils.commonDatabaseName(databaseProductName).toLowerCase();
|
||||
}
|
||||
catch (MetaDataAccessException ex) {
|
||||
throw new IllegalStateException("Unable to detect database type", ex);
|
||||
}
|
||||
@Override
|
||||
protected String getSchemaLocation() {
|
||||
return this.properties.getSchema();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue