From 92d6e5a14c2af7c31949c8d7769cc8ebd22d5829 Mon Sep 17 00:00:00 2001 From: Thomas Risberg Date: Fri, 7 Oct 2011 03:01:43 +0000 Subject: [PATCH] SPR-8270 Adding improved support for detecting current schema name for Oracle --- .../GenericTableMetaDataProvider.java | 32 +++++++++----- .../metadata/OracleTableMetaDataProvider.java | 44 +++++++++++++++++-- 2 files changed, 62 insertions(+), 14 deletions(-) diff --git a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/metadata/GenericTableMetaDataProvider.java b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/metadata/GenericTableMetaDataProvider.java index 3cd3e5109f1..fc160ec8b2c 100644 --- a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/metadata/GenericTableMetaDataProvider.java +++ b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/metadata/GenericTableMetaDataProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2011 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. @@ -66,7 +66,7 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider { private boolean generatedKeysColumnNameArraySupported = true; /** database products we know not supporting the use of a String[] for generated keys */ - private List productsNotSupportingGeneratedKeysColumnNameArray = + private List productsNotSupportingGeneratedKeysColumnNameArray = Arrays.asList("Apache Derby", "HSQL Database Engine"); /** Collection of TableParameterMetaData objects */ @@ -267,11 +267,17 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider { public String metaDataSchemaNameToUse(String schemaName) { if (schemaName == null) { - return schemaNameToUse(userName); + return schemaNameToUse(getDefaultSchema()); } return schemaNameToUse(schemaName); } + /** + * Provide access to default schema for subclasses. + */ + protected String getDefaultSchema() { + return userName; + } /** * Provide access to version info for subclasses. @@ -327,16 +333,19 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider { else { TableMetaData tmd; if (schemaName == null) { - tmd = tableMeta.get(userName.toUpperCase()); + tmd = tableMeta.get(getDefaultSchema()); + if (tmd == null) { + tmd = tableMeta.get(userName.toUpperCase()); + } if (tmd == null) { tmd = tableMeta.get("PUBLIC"); - if (tmd == null) { - tmd = tableMeta.get("DBO"); - } - if (tmd == null) { - throw new DataAccessResourceFailureException("Unable to locate table meta data for '" + - tableName + "' in the default schema"); - } + } + if (tmd == null) { + tmd = tableMeta.get("DBO"); + } + if (tmd == null) { + throw new DataAccessResourceFailureException("Unable to locate table meta data for '" + + tableName + "' in the default schema"); } } else { @@ -461,6 +470,7 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider { this.type = type; } + @SuppressWarnings("unused") public String getType() { return this.type; } diff --git a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/metadata/OracleTableMetaDataProvider.java b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/metadata/OracleTableMetaDataProvider.java index afaf351587e..326428a4c8d 100644 --- a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/metadata/OracleTableMetaDataProvider.java +++ b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/metadata/OracleTableMetaDataProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2011 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. @@ -17,9 +17,11 @@ package org.springframework.jdbc.core.metadata; import java.lang.reflect.Method; +import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.SQLException; +import java.sql.Types; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor; @@ -27,8 +29,12 @@ import org.springframework.util.ReflectionUtils; /** * Oracle-specific implementation of the {@link org.springframework.jdbc.core.metadata.TableMetaDataProvider}. - * Supports a feature for including synonyms in the metadata lookup. + * Supports a feature for including synonyms in the metadata lookup. Also supports lookup of current schema using + * the sys_context. * + *

Thanks to Mike Youngstrom and Bruce Campbell for submitting the original suggestion for the Oracle + * current schema lookup implementation. + * * @author Thomas Risberg * @author Juergen Hoeller * @since 3.0 @@ -36,6 +42,8 @@ import org.springframework.util.ReflectionUtils; public class OracleTableMetaDataProvider extends GenericTableMetaDataProvider { private final boolean includeSynonyms; + + private String defaultSchema; public OracleTableMetaDataProvider(DatabaseMetaData databaseMetaData) throws SQLException { @@ -45,8 +53,16 @@ public class OracleTableMetaDataProvider extends GenericTableMetaDataProvider { public OracleTableMetaDataProvider(DatabaseMetaData databaseMetaData, boolean includeSynonyms) throws SQLException { super(databaseMetaData); this.includeSynonyms = includeSynonyms; + lookupDefaultSchema(databaseMetaData); } + @Override + protected String getDefaultSchema() { + if (defaultSchema != null) { + return defaultSchema; + } + return super.getDefaultSchema(); + } @Override public void initializeWithTableColumnMetaData(DatabaseMetaData databaseMetaData, @@ -65,7 +81,7 @@ public class OracleTableMetaDataProvider extends GenericTableMetaDataProvider { } boolean isOracleCon; try { - Class oracleConClass = getClass().getClassLoader().loadClass("oracle.jdbc.OracleConnection"); + Class oracleConClass = getClass().getClassLoader().loadClass("oracle.jdbc.OracleConnection"); isOracleCon = oracleConClass.isInstance(con); } catch (ClassNotFoundException ex) { @@ -108,5 +124,27 @@ public class OracleTableMetaDataProvider extends GenericTableMetaDataProvider { throw new InvalidDataAccessApiUsageException("Couldn't reset Oracle Connection", ex); } } + + /* + * Oracle implementation for detecting current schema + * + * @param databaseMetaData + */ + private void lookupDefaultSchema(DatabaseMetaData databaseMetaData) { + try { + CallableStatement cstmt = null; + try { + cstmt = databaseMetaData.getConnection().prepareCall("{? = call sys_context('USERENV', 'CURRENT_SCHEMA')}"); + cstmt.registerOutParameter(1, Types.VARCHAR); + cstmt.execute(); + this.defaultSchema = cstmt.getString(1); + } + finally { + if (cstmt != null) { + cstmt.close(); + } + } + } catch (Exception ignore) {} + } }