diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactory.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactory.java index 1ba00bee1..924b745d6 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactory.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactory.java @@ -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; * * * @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 types = new ArrayList(); + + for(DatabaseType type : DatabaseType.values()){ + types.add(type.name()); + } + + return (String[])types.toArray(); } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SimpleDelegatingPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SimpleDelegatingPagingQueryProvider.java index 70decce20..aeffdb2c3 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SimpleDelegatingPagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SimpleDelegatingPagingQueryProvider.java @@ -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 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()); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProvider.java index 51e88fc60..61089c2bd 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProvider.java @@ -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 diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SybasePagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SybasePagingQueryProvider.java index 075dcaaa3..957de9eb1 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SybasePagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SybasePagingQueryProvider.java @@ -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 diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/DatabaseType.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/DatabaseType.java new file mode 100644 index 000000000..6c1c33918 --- /dev/null +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/DatabaseType.java @@ -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 nameMap; + + static{ + nameMap = new HashMap(); + 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); + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SimpleDelegatingPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SimpleDelegatingPagingQueryProviderTests.java index 6c20845a8..421a6495a 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SimpleDelegatingPagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SimpleDelegatingPagingQueryProviderTests.java @@ -8,7 +8,6 @@ import org.junit.Test; import org.junit.Assert; import org.junit.Before; import org.easymock.EasyMock; -import org.springframework.dao.InvalidDataAccessResourceUsageException; import javax.sql.DataSource; import java.sql.Connection; @@ -214,7 +213,7 @@ public class SimpleDelegatingPagingQueryProviderTests { try { pagingQueryProvider.init(ds); fail("Expected an InvalidDataAccessResourceUsageException since the MyDB database is not supported"); - } catch (InvalidDataAccessResourceUsageException e) { + } catch (IllegalArgumentException e) { // expected } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/DatabaseTypeTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/DatabaseTypeTests.java new file mode 100644 index 000000000..9dae0a6f1 --- /dev/null +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/DatabaseTypeTests.java @@ -0,0 +1,54 @@ +package org.springframework.batch.support; + +import static org.springframework.batch.support.DatabaseType.*; +import static org.junit.Assert.*; +import static org.easymock.EasyMock.*; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; + +import javax.sql.DataSource; + +import org.junit.Test; + +/** + * + * @author Lucas Ward + * + */ +public class DatabaseTypeTests { + + @Test + public void testFromProductName(){ + assertEquals(DERBY, fromProductName("Apache Derby")); + assertEquals(DB2, fromProductName("DB2")); + assertEquals(HSQL, fromProductName("HSQL Database Engine")); + assertEquals(SQLSERVER, fromProductName("Microsoft SQL Server")); + assertEquals(MYSQL, fromProductName("MySQL")); + assertEquals(ORACLE, fromProductName("Oracle")); + assertEquals(POSTGRES, fromProductName("PostgreSQL")); + assertEquals(SYBASE, fromProductName("Sybase")); + } + + @Test(expected=IllegalArgumentException.class) + public void testInvalidProductName(){ + + fromProductName("bad product name"); + } + + @Test + public void testFromMetaData() throws Exception{ + + DatabaseMetaData dmd = createMock(DatabaseMetaData.class); + DataSource ds = createMock(DataSource.class); + Connection con = createMock(Connection.class); + expect(ds.getConnection()).andReturn(con); + expect(con.getMetaData()).andReturn(dmd); + expect(dmd.getDatabaseProductName()).andReturn("Oracle"); + replay(dmd,ds,con); + + assertEquals(ORACLE, DatabaseType.fromMetaData(ds)); + + verify(dmd,ds,con); + } +}