001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.jdbc.core.metadata; 018 019import java.sql.DatabaseMetaData; 020import java.sql.SQLException; 021import javax.sql.DataSource; 022 023import org.apache.commons.logging.Log; 024import org.apache.commons.logging.LogFactory; 025 026import org.springframework.dao.DataAccessResourceFailureException; 027import org.springframework.jdbc.support.DatabaseMetaDataCallback; 028import org.springframework.jdbc.support.JdbcUtils; 029import org.springframework.jdbc.support.MetaDataAccessException; 030import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor; 031 032/** 033 * Factory used to create a {@link TableMetaDataProvider} implementation 034 * based on the type of database being used. 035 * 036 * @author Thomas Risberg 037 * @since 2.5 038 */ 039public class TableMetaDataProviderFactory { 040 041 private static final Log logger = LogFactory.getLog(TableMetaDataProviderFactory.class); 042 043 044 /** 045 * Create a {@link TableMetaDataProvider} based on the database meta-data. 046 * @param dataSource used to retrieve meta-data 047 * @param context the class that holds configuration and meta-data 048 * @return instance of the TableMetaDataProvider implementation to be used 049 */ 050 public static TableMetaDataProvider createMetaDataProvider(DataSource dataSource, TableMetaDataContext context) { 051 return createMetaDataProvider(dataSource, context, null); 052 } 053 054 /** 055 * Create a {@link TableMetaDataProvider} based on the database metadata. 056 * @param dataSource used to retrieve metadata 057 * @param context the class that holds configuration and metadata 058 * @param nativeJdbcExtractor the NativeJdbcExtractor to be used 059 * @return instance of the TableMetaDataProvider implementation to be used 060 */ 061 public static TableMetaDataProvider createMetaDataProvider(DataSource dataSource, 062 final TableMetaDataContext context, final NativeJdbcExtractor nativeJdbcExtractor) { 063 try { 064 return (TableMetaDataProvider) JdbcUtils.extractDatabaseMetaData(dataSource, 065 new DatabaseMetaDataCallback() { 066 @Override 067 public Object processMetaData(DatabaseMetaData databaseMetaData) throws SQLException { 068 String databaseProductName = 069 JdbcUtils.commonDatabaseName(databaseMetaData.getDatabaseProductName()); 070 boolean accessTableColumnMetaData = context.isAccessTableColumnMetaData(); 071 TableMetaDataProvider provider; 072 073 if ("Oracle".equals(databaseProductName)) { 074 provider = new OracleTableMetaDataProvider( 075 databaseMetaData, context.isOverrideIncludeSynonymsDefault()); 076 } 077 else if ("PostgreSQL".equals(databaseProductName)) { 078 provider = new PostgresTableMetaDataProvider(databaseMetaData); 079 } 080 else if ("Apache Derby".equals(databaseProductName)) { 081 provider = new DerbyTableMetaDataProvider(databaseMetaData); 082 } 083 else if ("HSQL Database Engine".equals(databaseProductName)) { 084 provider = new HsqlTableMetaDataProvider(databaseMetaData); 085 } 086 else { 087 provider = new GenericTableMetaDataProvider(databaseMetaData); 088 } 089 if (nativeJdbcExtractor != null) { 090 provider.setNativeJdbcExtractor(nativeJdbcExtractor); 091 } 092 093 if (logger.isDebugEnabled()) { 094 logger.debug("Using " + provider.getClass().getSimpleName()); 095 } 096 provider.initializeWithMetaData(databaseMetaData); 097 if (accessTableColumnMetaData) { 098 provider.initializeWithTableColumnMetaData(databaseMetaData, 099 context.getCatalogName(), context.getSchemaName(), context.getTableName()); 100 } 101 return provider; 102 } 103 }); 104 } 105 catch (MetaDataAccessException ex) { 106 throw new DataAccessResourceFailureException("Error retrieving database meta-data", ex); 107 } 108 } 109 110}