IN PROGRESS - issue BATCH-792: Automatically detect database type in JobRepositoryFactoryBean

http://jira.springframework.org/browse/BATCH-792

JobRepositoryFactoryBean now detects the database type by the meta data.  There is also now an enum representing the DatabaseType.
This commit is contained in:
lucasward
2008-09-05 23:23:13 +00:00
parent 34c2fce32f
commit fc2de248f6
7 changed files with 187 additions and 67 deletions

View File

@@ -15,8 +15,14 @@
*/
package org.springframework.batch.item.database.support;
import static org.springframework.batch.support.DatabaseType.*;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.batch.support.DatabaseType;
import org.springframework.jdbc.support.incrementer.DB2SequenceMaxValueIncrementer;
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
import org.springframework.jdbc.support.incrementer.DerbyMaxValueIncrementer;
@@ -45,26 +51,10 @@ import org.springframework.jdbc.support.incrementer.SybaseMaxValueIncrementer;
* </ul>
*
* @author Lucas Ward
*
* @see DatabaseType
*/
public class DefaultDataFieldMaxValueIncrementerFactory implements DataFieldMaxValueIncrementerFactory {
static final String DB_TYPE_DB2 = "db2";
static final String DB_TYPE_DERBY = "derby";
static final String DB_TYPE_HSQL = "hsql";
static final String DB_TYPE_MYSQL = "mysql";
static final String DB_TYPE_ORACLE = "oracle";
static final String DB_TYPE_POSTGRES = "postgres";
static final String DB_TYPE_SQLSERVER = "sqlserver";
static final String DB_TYPE_SYBASE = "sybase";
private DataSource dataSource;
private String incrementerColumnName = "ID";
@@ -86,28 +76,30 @@ public class DefaultDataFieldMaxValueIncrementerFactory implements DataFieldMaxV
}
public DataFieldMaxValueIncrementer getIncrementer(String incrementerType, String incrementerName) {
if (DB_TYPE_DB2.equals(incrementerType)) {
DatabaseType databaseType = DatabaseType.valueOf(incrementerType.toUpperCase());
if (databaseType == DB2) {
return new DB2SequenceMaxValueIncrementer(dataSource, incrementerName);
}
else if (DB_TYPE_DERBY.equals(incrementerType)) {
else if (databaseType == DERBY) {
return new DerbyMaxValueIncrementer(dataSource, incrementerName, incrementerColumnName);
}
else if (DB_TYPE_HSQL.equals(incrementerType)) {
else if (databaseType == HSQL) {
return new HsqlMaxValueIncrementer(dataSource, incrementerName, incrementerColumnName);
}
else if (DB_TYPE_MYSQL.equals(incrementerType)) {
else if (databaseType == MYSQL) {
return new MySQLMaxValueIncrementer(dataSource, incrementerName, incrementerColumnName);
}
else if (DB_TYPE_ORACLE.equals(incrementerType)) {
else if (databaseType == ORACLE) {
return new OracleSequenceMaxValueIncrementer(dataSource, incrementerName);
}
else if (DB_TYPE_POSTGRES.equals(incrementerType)) {
else if (databaseType == POSTGRES) {
return new PostgreSQLSequenceMaxValueIncrementer(dataSource, incrementerName);
}
else if (DB_TYPE_SQLSERVER.equals(incrementerType)) {
else if (databaseType == SQLSERVER) {
return new SqlServerMaxValueIncrementer(dataSource, incrementerName, incrementerColumnName);
}
else if (DB_TYPE_SYBASE.equals(incrementerType)) {
else if (databaseType == SYBASE) {
return new SybaseMaxValueIncrementer(dataSource, incrementerName, incrementerColumnName);
}
throw new IllegalArgumentException("databaseType argument was not on the approved list");
@@ -115,20 +107,23 @@ public class DefaultDataFieldMaxValueIncrementerFactory implements DataFieldMaxV
}
public boolean isSupportedIncrementerType(String incrementerType) {
if (!DB_TYPE_DB2.equals(incrementerType) && !DB_TYPE_DERBY.equals(incrementerType)
&& !DB_TYPE_HSQL.equals(incrementerType) && !DB_TYPE_MYSQL.equals(incrementerType)
&& !DB_TYPE_ORACLE.equals(incrementerType) && !DB_TYPE_POSTGRES.equals(incrementerType)
&& !DB_TYPE_SQLSERVER.equals(incrementerType) && !DB_TYPE_SYBASE.equals(incrementerType)) {
return false;
}
else {
return true;
for(DatabaseType type : DatabaseType.values()){
if(type.name().equals(incrementerType.toUpperCase())){
return true;
}
}
return false;
}
public String[] getSupportedIncrementerTypes() {
return new String[] { DB_TYPE_DB2, DB_TYPE_DERBY, DB_TYPE_HSQL, DB_TYPE_MYSQL,
DB_TYPE_ORACLE, DB_TYPE_POSTGRES, DB_TYPE_SQLSERVER, DB_TYPE_SYBASE };
List<String> types = new ArrayList<String>();
for(DatabaseType type : DatabaseType.values()){
types.add(type.name());
}
return (String[])types.toArray();
}
}

View File

@@ -1,11 +1,11 @@
package org.springframework.batch.item.database.support;
import org.springframework.jdbc.support.JdbcUtils;
import static org.springframework.batch.support.DatabaseType.*;
import org.springframework.batch.support.DatabaseType;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
import javax.sql.DataSource;
import java.util.List;
import java.util.Arrays;
/**
* Generic Paging Query Provider using standard SQL:2003 windowing functions. These features are supported by
@@ -16,53 +16,41 @@ import java.util.Arrays;
*/
public class SimpleDelegatingPagingQueryProvider extends AbstractSqlPagingQueryProvider {
/* List of supported database products */
public static final List<String> supportedDatabaseProducts = Arrays.asList(
"Apache Derby",
"DB2",
"HSQL Database Engine",
"Microsoft SQL Server",
"MySQL",
"Oracle",
"PostgreSQL",
"Sybase"
);
AbstractSqlPagingQueryProvider delegate;
@Override
public void init(DataSource dataSource) throws Exception {
super.init(dataSource);
String databaseProductName = JdbcUtils.commonDatabaseName(
JdbcUtils.extractDatabaseMetaData(dataSource, "getDatabaseProductName").toString());
if ("Apache Derby".equals(databaseProductName)) {
DatabaseType type = DatabaseType.fromMetaData(dataSource);
if (type == DERBY) {
delegate = new DerbyPagingQueryProvider();
}
else if ("DB2".equals(databaseProductName)) {
else if (type == DB2) {
delegate = new Db2PagingQueryProvider();
}
else if ("HSQL Database Engine".equals(databaseProductName)) {
else if (type == HSQL) {
delegate = new HsqlPagingQueryProvider();
}
else if ("Microsoft SQL Server".equals(databaseProductName)) {
else if (type == SQLSERVER) {
delegate = new SqlServerPagingQueryProvider();
}
else if ("MySQL".equals(databaseProductName)) {
else if (type == MYSQL) {
delegate = new MySqlPagingQueryProvider();
}
else if ("Oracle".equals(databaseProductName)) {
else if (type == ORACLE) {
delegate = new OraclePagingQueryProvider();
}
else if ("PostgreSQL".equals(databaseProductName)) {
else if (type == POSTGRES) {
delegate = new PostgresPagingQueryProvider();
}
else if ("Sybase".equals(databaseProductName)) {
else if (type == SYBASE) {
delegate = new SybasePagingQueryProvider();
}
else {
throw new InvalidDataAccessResourceUsageException(databaseProductName +
throw new InvalidDataAccessResourceUsageException(type.name() +
" is not a supported database. The supported databases are " +
supportedDatabaseProducts.toString());
type.values().toString());
}
delegate.setSelectClause(this.getSelectClause());
delegate.setFromClause(this.getFromClause());

View File

@@ -1,7 +1,7 @@
package org.springframework.batch.item.database.support;
/**
* Oracle implementation of a {@link org.springframework.batch.item.database.support.PagingQueryProvider} using
* Sql Server implementation of a {@link org.springframework.batch.item.database.support.PagingQueryProvider} using
* database specific features.
*
* @author Thomas Risberg

View File

@@ -1,7 +1,7 @@
package org.springframework.batch.item.database.support;
/**
* Oracle implementation of a {@link PagingQueryProvider} using
* Sybase implementation of a {@link PagingQueryProvider} using
* database specific features.
*
* @author Thomas Risberg

View File

@@ -0,0 +1,84 @@
/**
*
*/
package org.springframework.batch.support;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.jdbc.support.MetaDataAccessException;
/**
* Enum representing a database type, such as DB2 or oracle. The type also
* contains a product name, which is expected to the same as the product name
* provided by the database driver's metadata.
*
* @author Lucas Ward
* @since 2.0
*/
public enum DatabaseType {
DERBY("Apache Derby"),
DB2("DB2"),
HSQL("HSQL Database Engine"),
SQLSERVER("Microsoft SQL Server"),
MYSQL("MySQL"),
ORACLE("Oracle"),
POSTGRES("PostgreSQL"),
SYBASE("Sybase");
private static final Map<String, DatabaseType> nameMap;
static{
nameMap = new HashMap<String, DatabaseType>();
for(DatabaseType type: values()){
nameMap.put(type.getProductName(), type);
}
}
//A description is necessary due to the length of database descriptions
//in metadata.
private final String productName;
private DatabaseType(String productName) {
this.productName = productName;
}
public String getProductName() {
return productName;
}
/**
* Static method to obtain a DatabaseType from the provided product name.
*
* @param productName
* @return DatabaseType for given product name.
* @throws IllegalArgumentException if none is found.
*/
public static DatabaseType fromProductName(String productName){
if(!nameMap.containsKey(productName)){
throw new IllegalArgumentException("DatabaseType not found for product name: [" +
productName + "]");
}
else{
return nameMap.get(productName);
}
}
/**
* Convenience method that pulls a database product name from the DataSource's metadata.
*
* @param dataSource
* @return DatabaseType
* @throws MetaDataAccessException
*/
public static DatabaseType fromMetaData(DataSource dataSource) throws MetaDataAccessException{
String databaseProductName = JdbcUtils.commonDatabaseName(
JdbcUtils.extractDatabaseMetaData(dataSource, "getDatabaseProductName").toString());
return fromProductName(databaseProductName);
}
}