Merge pull request #6543 from vpavic:database-initializers
* pr/6543: Polish contribution Improve database initializers
This commit is contained in:
commit
d5b2f67b5f
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Base class used for database initialization.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public abstract class AbstractDatabaseInitializer {
|
||||
|
||||
private static final String PLATFORM_PLACEHOLDER = "@@platform@@";
|
||||
|
||||
private final DataSource dataSource;
|
||||
|
||||
private final ResourceLoader resourceLoader;
|
||||
|
||||
protected 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 = 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 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.getId();
|
||||
}
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
* 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.
|
||||
|
|
@ -16,63 +16,46 @@
|
|||
|
||||
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;
|
||||
private final 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();
|
||||
@Override
|
||||
protected boolean isEnabled() {
|
||||
return this.properties.getInitializer().isEnabled();
|
||||
}
|
||||
catch (MetaDataAccessException ex) {
|
||||
throw new IllegalStateException("Unable to detect database type", ex);
|
||||
|
||||
@Override
|
||||
protected String getSchemaLocation() {
|
||||
return this.properties.getSchema();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDatabaseName() {
|
||||
String databaseName = super.getDatabaseName();
|
||||
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 final 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,77 +33,77 @@ public enum DatabaseDriver {
|
|||
/**
|
||||
* Unknown type.
|
||||
*/
|
||||
UNKNOWN(null, null),
|
||||
UNKNOWN("unknown", null, null),
|
||||
|
||||
/**
|
||||
* Apache Derby.
|
||||
*/
|
||||
DERBY("Apache Derby", "org.apache.derby.jdbc.EmbeddedDriver",
|
||||
DERBY("derby", "Apache Derby", "org.apache.derby.jdbc.EmbeddedDriver",
|
||||
"org.apache.derby.jdbc.EmbeddedXADataSource",
|
||||
"SELECT 1 FROM SYSIBM.SYSDUMMY1"),
|
||||
|
||||
/**
|
||||
* H2.
|
||||
*/
|
||||
H2("H2", "org.h2.Driver", "org.h2.jdbcx.JdbcDataSource", "SELECT 1"),
|
||||
H2("h2", "H2", "org.h2.Driver", "org.h2.jdbcx.JdbcDataSource", "SELECT 1"),
|
||||
|
||||
/**
|
||||
* HyperSQL DataBase.
|
||||
*/
|
||||
HSQLDB("HSQL Database Engine", "org.hsqldb.jdbc.JDBCDriver",
|
||||
HSQLDB("hsqldb", "HSQL Database Engine", "org.hsqldb.jdbc.JDBCDriver",
|
||||
"org.hsqldb.jdbc.pool.JDBCXADataSource",
|
||||
"SELECT COUNT(*) FROM INFORMATION_SCHEMA.SYSTEM_USERS"),
|
||||
|
||||
/**
|
||||
* SQL Lite.
|
||||
*/
|
||||
SQLITE("SQLite", "org.sqlite.JDBC"),
|
||||
SQLITE("sqlite", "SQLite", "org.sqlite.JDBC"),
|
||||
|
||||
/**
|
||||
* MySQL.
|
||||
*/
|
||||
MYSQL("MySQL", "com.mysql.jdbc.Driver",
|
||||
MYSQL("mysql", "MySQL", "com.mysql.jdbc.Driver",
|
||||
"com.mysql.jdbc.jdbc2.optional.MysqlXADataSource", "SELECT 1"),
|
||||
|
||||
/**
|
||||
* Maria DB.
|
||||
*/
|
||||
MARIADB("MySQL", "org.mariadb.jdbc.Driver", "org.mariadb.jdbc.MariaDbDataSource",
|
||||
"SELECT 1"),
|
||||
MARIADB("maridb", "MySQL", "org.mariadb.jdbc.Driver",
|
||||
"org.mariadb.jdbc.MariaDbDataSource", "SELECT 1"),
|
||||
|
||||
/**
|
||||
* Google App Engine.
|
||||
*/
|
||||
GAE(null, "com.google.appengine.api.rdbms.AppEngineDriver"),
|
||||
GAE("gae", null, "com.google.appengine.api.rdbms.AppEngineDriver"),
|
||||
|
||||
/**
|
||||
* Oracle.
|
||||
*/
|
||||
ORACLE("Oracle", "oracle.jdbc.OracleDriver",
|
||||
ORACLE("oracle", "Oracle", "oracle.jdbc.OracleDriver",
|
||||
"oracle.jdbc.xa.client.OracleXADataSource", "SELECT 'Hello' from DUAL"),
|
||||
|
||||
/**
|
||||
* Postgres.
|
||||
*/
|
||||
POSTGRESQL("PostgreSQL", "org.postgresql.Driver", "org.postgresql.xa.PGXADataSource",
|
||||
"SELECT 1"),
|
||||
POSTGRESQL("postgresql", "PostgreSQL", "org.postgresql.Driver",
|
||||
"org.postgresql.xa.PGXADataSource", "SELECT 1"),
|
||||
|
||||
/**
|
||||
* jTDS. As it can be used for several databases, there isn't a single product name we
|
||||
* could rely on.
|
||||
*/
|
||||
JTDS(null, "net.sourceforge.jtds.jdbc.Driver"),
|
||||
JTDS("jtds", null, "net.sourceforge.jtds.jdbc.Driver"),
|
||||
|
||||
/**
|
||||
* SQL Server.
|
||||
*/
|
||||
SQLSERVER("SQL SERVER", "com.microsoft.sqlserver.jdbc.SQLServerDriver",
|
||||
SQLSERVER("sqlserver", "SQL SERVER", "com.microsoft.sqlserver.jdbc.SQLServerDriver",
|
||||
"com.microsoft.sqlserver.jdbc.SQLServerXADataSource", "SELECT 1"),
|
||||
|
||||
/**
|
||||
* Firebird.
|
||||
*/
|
||||
FIREBIRD("Firebird", "org.firebirdsql.jdbc.FBDriver",
|
||||
FIREBIRD("firebird", "Firebird", "org.firebirdsql.jdbc.FBDriver",
|
||||
"org.firebirdsql.pool.FBConnectionPoolDataSource",
|
||||
"SELECT 1 FROM RDB$DATABASE") {
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ public enum DatabaseDriver {
|
|||
/**
|
||||
* DB2 Server.
|
||||
*/
|
||||
DB2("DB2", "com.ibm.db2.jcc.DB2Driver", "com.ibm.db2.jcc.DB2XADataSource",
|
||||
DB2("db2", "DB2", "com.ibm.db2.jcc.DB2Driver", "com.ibm.db2.jcc.DB2XADataSource",
|
||||
"SELECT 1 FROM SYSIBM.SYSDUMMY1") {
|
||||
|
||||
@Override
|
||||
|
|
@ -130,7 +130,7 @@ public enum DatabaseDriver {
|
|||
/**
|
||||
* DB2 AS400 Server.
|
||||
*/
|
||||
DB2_AS400("DB2 UDB for AS/400", "com.ibm.as400.access.AS400JDBCDriver",
|
||||
DB2_AS400("db2", "DB2 UDB for AS/400", "com.ibm.as400.access.AS400JDBCDriver",
|
||||
"com.ibm.as400.access.AS400JDBCXADataSource",
|
||||
"SELECT 1 FROM SYSIBM.SYSDUMMY1") {
|
||||
|
||||
|
|
@ -144,14 +144,16 @@ public enum DatabaseDriver {
|
|||
/**
|
||||
* Teradata.
|
||||
*/
|
||||
TERADATA("Teradata", "com.teradata.jdbc.TeraDriver"),
|
||||
TERADATA("teradata", "Teradata", "com.teradata.jdbc.TeraDriver"),
|
||||
|
||||
/**
|
||||
* Informix.
|
||||
*/
|
||||
INFORMIX("Informix Dynamic Server", "com.informix.jdbc.IfxDriver", null,
|
||||
INFORMIX("informix", "Informix Dynamic Server", "com.informix.jdbc.IfxDriver", null,
|
||||
"select count(*) from systables");
|
||||
|
||||
private final String id;
|
||||
|
||||
private final String productName;
|
||||
|
||||
private final String driverClassName;
|
||||
|
|
@ -160,22 +162,32 @@ public enum DatabaseDriver {
|
|||
|
||||
private final String validationQuery;
|
||||
|
||||
DatabaseDriver(String name, String driverClassName) {
|
||||
this(name, driverClassName, null);
|
||||
DatabaseDriver(String id, String name, String driverClassName) {
|
||||
this(id, name, driverClassName, null);
|
||||
}
|
||||
|
||||
DatabaseDriver(String name, String driverClassName, String xaDataSourceClassName) {
|
||||
this(name, driverClassName, xaDataSourceClassName, null);
|
||||
DatabaseDriver(String id, String name, String driverClassName,
|
||||
String xaDataSourceClassName) {
|
||||
this(id, name, driverClassName, xaDataSourceClassName, null);
|
||||
}
|
||||
|
||||
DatabaseDriver(String productName, String driverClassName,
|
||||
DatabaseDriver(String id, String productName, String driverClassName,
|
||||
String xaDataSourceClassName, String validationQuery) {
|
||||
this.id = id;
|
||||
this.productName = productName;
|
||||
this.driverClassName = driverClassName;
|
||||
this.xaDataSourceClassName = xaDataSourceClassName;
|
||||
this.validationQuery = validationQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the identifier of this driver.
|
||||
* @return the identifier
|
||||
*/
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
protected boolean matchProductName(String productName) {
|
||||
return this.productName != null && this.productName.equalsIgnoreCase(productName);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue