提交 0f924820 编写于 作者: J Juergen Hoeller

revised OracleTableMetaDataProvider for reliable Oracle Connection detection;...

revised OracleTableMetaDataProvider for reliable Oracle Connection detection; autodetect JdbcTemplate's NativeJdbcExtractor (SPR-7611)
上级 1f1577e3
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2010 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.
......@@ -33,8 +33,8 @@ import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
/**
* A generic implementation of the {@link TableMetaDataProvider} that should provide enough features for all supported
* databases.
* A generic implementation of the {@link TableMetaDataProvider} that should provide
* enough features for all supported databases.
*
* @author Thomas Risberg
* @since 2.5
......@@ -67,30 +67,23 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
/** database products we know not supporting the use of a String[] for generated keys */
private List productsNotSupportingGeneratedKeysColumnNameArray =
Arrays.asList(new String[] {"Apache Derby", "HSQL Database Engine"});
Arrays.asList("Apache Derby", "HSQL Database Engine");
/** Collection of TableParameterMetaData objects */
private List<TableParameterMetaData> insertParameterMetaData = new ArrayList<TableParameterMetaData>();
/** NativeJdbcExtractor that can be used to retrieve the native connection */
protected NativeJdbcExtractor nativeJdbcExtractor = null;
private NativeJdbcExtractor nativeJdbcExtractor;
/**
* Constructor used to initialize with provided database meta data.
* @param databaseMetaData meta data to be used
* @throws SQLException
*/
protected GenericTableMetaDataProvider(DatabaseMetaData databaseMetaData) throws SQLException {
userName = databaseMetaData.getUserName();
this.userName = databaseMetaData.getUserName();
}
/**
* Get whether identifiers use upper case
*/
public boolean isStoresUpperCaseIdentifiers() {
return storesUpperCaseIdentifiers;
}
/**
* Specify whether identifiers use upper case
......@@ -100,29 +93,36 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
}
/**
* Get whether identifiers use lower case
* Get whether identifiers use upper case
*/
public boolean isStoresLowerCaseIdentifiers() {
return storesLowerCaseIdentifiers;
public boolean isStoresUpperCaseIdentifiers() {
return this.storesUpperCaseIdentifiers;
}
/**
* Specify whether identifiers use lower case
* Specify whether identifiers use lower case.
*/
public void setStoresLowerCaseIdentifiers(boolean storesLowerCaseIdentifiers) {
this.storesLowerCaseIdentifiers = storesLowerCaseIdentifiers;
}
/**
* Get whether identifiers use lower case
*/
public boolean isStoresLowerCaseIdentifiers() {
return this.storesLowerCaseIdentifiers;
}
public boolean isTableColumnMetaDataUsed() {
return tableColumnMetaDataUsed;
return this.tableColumnMetaDataUsed;
}
public List<TableParameterMetaData> getTableParameterMetaData() {
return insertParameterMetaData;
return this.insertParameterMetaData;
}
public boolean isGetGeneratedKeysSupported() {
return getGeneratedKeysSupported;
return this.getGeneratedKeysSupported;
}
public boolean isGetGeneratedKeysSimulated(){
......@@ -140,10 +140,6 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
this.getGeneratedKeysSupported = getGeneratedKeysSupported;
}
public boolean isGeneratedKeysColumnNameArraySupported() {
return generatedKeysColumnNameArraySupported;
}
/**
* Specify whether a column name array is supported for generated keys
*/
......@@ -151,12 +147,20 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
this.generatedKeysColumnNameArraySupported = generatedKeysColumnNameArraySupported;
}
public boolean isGeneratedKeysColumnNameArraySupported() {
return this.generatedKeysColumnNameArraySupported;
}
public void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor) {
this.nativeJdbcExtractor = nativeJdbcExtractor;
}
public void initializeWithMetaData(DatabaseMetaData databaseMetaData) throws SQLException {
protected NativeJdbcExtractor getNativeJdbcExtractor() {
return this.nativeJdbcExtractor;
}
public void initializeWithMetaData(DatabaseMetaData databaseMetaData) throws SQLException {
try {
if (databaseMetaData.supportsGetGeneratedKeys()) {
logger.debug("GetGeneratedKeys is supported");
......@@ -172,7 +176,7 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
}
try {
String databaseProductName = databaseMetaData.getDatabaseProductName();
if (productsNotSupportingGeneratedKeysColumnNameArray.contains(databaseProductName)) {
if (this.productsNotSupportingGeneratedKeysColumnNameArray.contains(databaseProductName)) {
logger.debug("GeneratedKeysColumnNameArray is not supported for " + databaseProductName);
setGeneratedKeysColumnNameArraySupported(false);
}
......@@ -185,7 +189,7 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
logger.warn("Error retrieving 'DatabaseMetaData.getDatabaseProductName' - " + se.getMessage());
}
try {
databaseVersion = databaseMetaData.getDatabaseProductVersion();
this.databaseVersion = databaseMetaData.getDatabaseProductVersion();
}
catch (SQLException se) {
logger.warn("Error retrieving 'DatabaseMetaData.getDatabaseProductVersion' - " + se.getMessage());
......@@ -205,47 +209,56 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
}
public void initializeWithTableColumnMetaData(DatabaseMetaData databaseMetaData, String catalogName, String schemaName, String tableName)
throws SQLException {
tableColumnMetaDataUsed = true;
public void initializeWithTableColumnMetaData(DatabaseMetaData databaseMetaData, String catalogName,
String schemaName, String tableName) throws SQLException {
this.tableColumnMetaDataUsed = true;
locateTableAndProcessMetaData(databaseMetaData, catalogName, schemaName, tableName);
}
public String tableNameToUse(String tableName) {
if (tableName == null)
if (tableName == null) {
return null;
else if (isStoresUpperCaseIdentifiers())
}
else if (isStoresUpperCaseIdentifiers()) {
return tableName.toUpperCase();
else if(isStoresLowerCaseIdentifiers())
}
else if(isStoresLowerCaseIdentifiers()) {
return tableName.toLowerCase();
else
}
else {
return tableName;
}
}
public String catalogNameToUse(String catalogName) {
if (catalogName == null)
if (catalogName == null) {
return null;
else if (isStoresUpperCaseIdentifiers())
}
else if (isStoresUpperCaseIdentifiers()) {
return catalogName.toUpperCase();
else if(isStoresLowerCaseIdentifiers())
}
else if(isStoresLowerCaseIdentifiers()) {
return catalogName.toLowerCase();
else
return catalogName;
}
else {
return catalogName;
}
}
public String schemaNameToUse(String schemaName) {
if (schemaName == null)
if (schemaName == null) {
return null;
else if (isStoresUpperCaseIdentifiers())
}
else if (isStoresUpperCaseIdentifiers()) {
return schemaName.toUpperCase();
else if(isStoresLowerCaseIdentifiers())
}
else if(isStoresLowerCaseIdentifiers()) {
return schemaName.toLowerCase();
else
return schemaName;
}
else {
return schemaName;
}
}
public String metaDataCatalogNameToUse(String catalogName) {
......@@ -261,19 +274,20 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
/**
* Provide access to version info for subclasses
* Provide access to version info for subclasses.
*/
protected String getDatabaseVersion() {
return databaseVersion;
return this.databaseVersion;
}
/**
* Method supporting the metedata processing for a table
* Method supporting the metedata processing for a table.
*/
private void locateTableAndProcessMetaData(DatabaseMetaData databaseMetaData, String catalogName, String schemaName, String tableName) {
private void locateTableAndProcessMetaData(DatabaseMetaData databaseMetaData, String catalogName,
String schemaName, String tableName) {
Map<String, TableMetaData> tableMeta = new HashMap<String, TableMetaData>();
ResultSet tables = null;
try {
tables = databaseMetaData.getTables(
catalogNameToUse(catalogName),
......@@ -311,7 +325,7 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
logger.warn("Unable to locate table meta data for '" + tableName +"' -- column names must be provided");
}
else {
TableMetaData tmd = null;
TableMetaData tmd;
if (schemaName == null) {
tmd = tableMeta.get(userName.toUpperCase());
if (tmd == null) {
......@@ -320,14 +334,16 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
tmd = tableMeta.get("DBO");
}
if (tmd == null) {
throw new DataAccessResourceFailureException("Unable to locate table meta data for '" + tableName + "' in the default schema");
throw new DataAccessResourceFailureException("Unable to locate table meta data for '" +
tableName + "' in the default schema");
}
}
}
else {
tmd = tableMeta.get(schemaName.toUpperCase());
if (tmd == null) {
throw new DataAccessResourceFailureException("Unable to locate table meta data for '" + tableName + "' in the '" + schemaName + "' schema");
throw new DataAccessResourceFailureException("Unable to locate table meta data for '" +
tableName + "' in the '" + schemaName + "' schema");
}
}
......@@ -378,7 +394,7 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
dataType,
nullable
);
insertParameterMetaData.add(meta);
this.insertParameterMetaData.add(meta);
if (logger.isDebugEnabled()) {
logger.debug("Retrieved metadata: "
+ meta.getParameterName() +
......@@ -389,7 +405,7 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
}
}
catch (SQLException se) {
logger.warn("Error while retreiving metadata for table columns: " + se.getMessage());
logger.warn("Error while retrieving metadata for table columns: " + se.getMessage());
}
finally {
try {
......@@ -397,7 +413,7 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
tableColumns.close();
}
catch (SQLException se) {
logger.warn("Problem closing resultset for table column metadata " + se.getMessage());
logger.warn("Problem closing ResultSet for table column metadata " + se.getMessage());
}
}
......@@ -405,45 +421,49 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
/**
* Class representing table meta data
* Inner class representing table meta data.
*/
private class TableMetaData {
private static class TableMetaData {
private String catalogName;
private String schemaName;
private String tableName;
private String type;
private String tableName;
public String getCatalogName() {
return catalogName;
}
private String type;
public void setCatalogName(String catalogName) {
this.catalogName = catalogName;
}
public String getSchemaName() {
return schemaName;
public String getCatalogName() {
return this.catalogName;
}
public void setSchemaName(String schemaName) {
this.schemaName = schemaName;
}
public String getTableName() {
return tableName;
public String getSchemaName() {
return this.schemaName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getType() {
return type;
public String getTableName() {
return this.tableName;
}
public void setType(String type) {
this.type = type;
}
public String getType() {
return this.type;
}
}
}
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 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.
......@@ -22,17 +22,20 @@ import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
import org.springframework.util.ReflectionUtils;
/**
* The Oracle specific implementation of the {@link org.springframework.jdbc.core.metadata.TableMetaDataProvider}.
* Oracle-specific implementation of the {@link org.springframework.jdbc.core.metadata.TableMetaDataProvider}.
* Supports a feature for including synonyms in the metadata lookup.
*
* @author Thomas Risberg
* @author Juergen Hoeller
* @since 3.0
*/
public class OracleTableMetaDataProvider extends GenericTableMetaDataProvider {
private boolean includeSynonyms;
private final boolean includeSynonyms;
public OracleTableMetaDataProvider(DatabaseMetaData databaseMetaData) throws SQLException {
......@@ -49,67 +52,61 @@ public class OracleTableMetaDataProvider extends GenericTableMetaDataProvider {
public void initializeWithTableColumnMetaData(DatabaseMetaData databaseMetaData,
String catalogName, String schemaName, String tableName) throws SQLException {
Connection con = null;
if (nativeJdbcExtractor == null) {
con = databaseMetaData.getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Using meta data JDBC connection: " + con.getClass().getName());
}
}
else {
con = nativeJdbcExtractor.getNativeConnection(databaseMetaData.getConnection());
if (logger.isDebugEnabled()) {
logger.debug("Using native JDBC connection: " + con.getClass().getName());
}
if (!this.includeSynonyms) {
logger.debug("Defaulting to no synonyms in table metadata lookup");
super.initializeWithTableColumnMetaData(databaseMetaData, catalogName, schemaName, tableName);
return;
}
Method methodToInvoke = null;
Boolean origValueForIncludeSynonyms = null;
if (includeSynonyms) {
if (con.getClass().getName().startsWith("oracle")) {
if (logger.isDebugEnabled()) {
logger.debug("Including synonyms in table metadata lookup.");
}
}
else {
logger.warn("Unable to include synonyms in table metadata lookup. Connection used for " +
"DatabaseMetaData is not recognized as an Oracle connection; " +
"class is " + con.getClass().getName());
}
Connection con = databaseMetaData.getConnection();
NativeJdbcExtractor nativeJdbcExtractor = getNativeJdbcExtractor();
if (nativeJdbcExtractor != null) {
con = nativeJdbcExtractor.getNativeConnection(con);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Defaulting to no synonyms in table metadata lookup.");
boolean isOracleCon;
try {
Class oracleConClass = getClass().getClassLoader().loadClass("oracle.jdbc.OracleConnection");
isOracleCon = oracleConClass.isInstance(con);
}
catch (ClassNotFoundException ex) {
if (logger.isInfoEnabled()) {
logger.info("Couldn't find Oracle JDBC API: " + ex);
}
isOracleCon = false;
}
if (includeSynonyms && con.getClass().getName().startsWith("oracle")) {
try {
methodToInvoke = con.getClass().getMethod("getIncludeSynonyms", (Class[]) null);
methodToInvoke.setAccessible(true);
origValueForIncludeSynonyms = (Boolean)methodToInvoke.invoke(con);
methodToInvoke = con.getClass().getMethod("setIncludeSynonyms", new Class[] {boolean.class});
methodToInvoke.setAccessible(true);
methodToInvoke.invoke(con, Boolean.TRUE);
}
catch (Exception ex) {
throw new InvalidDataAccessApiUsageException(
"Couldn't initialize Oracle Connection.", ex);
}
if (!isOracleCon) {
logger.warn("Unable to include synonyms in table metadata lookup. Connection used for " +
"DatabaseMetaData is not recognized as an Oracle connection: " + con);
super.initializeWithTableColumnMetaData(databaseMetaData, catalogName, schemaName, tableName);
return;
}
logger.debug("Including synonyms in table metadata lookup");
Method setIncludeSynonyms;
Boolean originalValueForIncludeSynonyms;
try {
Method getIncludeSynonyms = con.getClass().getMethod("getIncludeSynonyms", (Class[]) null);
ReflectionUtils.makeAccessible(getIncludeSynonyms);
originalValueForIncludeSynonyms = (Boolean) getIncludeSynonyms.invoke(con);
setIncludeSynonyms = con.getClass().getMethod("setIncludeSynonyms", new Class[] {boolean.class});
ReflectionUtils.makeAccessible(setIncludeSynonyms);
setIncludeSynonyms.invoke(con, Boolean.TRUE);
}
catch (Exception ex) {
throw new InvalidDataAccessApiUsageException("Couldn't prepare Oracle Connection", ex);
}
super.initializeWithTableColumnMetaData(databaseMetaData, catalogName, schemaName, tableName);
if (includeSynonyms && con.getClass().getName().startsWith("oracle")) {
try {
methodToInvoke = con.getClass().getMethod("setIncludeSynonyms", new Class[] {boolean.class});
methodToInvoke.setAccessible(true);
methodToInvoke.invoke(con, origValueForIncludeSynonyms);
}
catch (Exception ex) {
throw new InvalidDataAccessApiUsageException(
"Couldn't restore Oracle Connection.", ex);
}
try {
setIncludeSynonyms.invoke(con, originalValueForIncludeSynonyms);
}
catch (Exception ex) {
throw new InvalidDataAccessApiUsageException("Couldn't reset Oracle Connection", ex);
}
}
}
\ No newline at end of file
}
......@@ -72,7 +72,8 @@ public class TableMetaDataContext {
private boolean generatedKeyColumnsUsed = false;
/** NativeJdbcExtractor to be used to retrieve the native connection */
NativeJdbcExtractor nativeJdbcExtractor = null;
NativeJdbcExtractor nativeJdbcExtractor;
/**
* Set the name of the table for this context.
......@@ -162,7 +163,7 @@ public class TableMetaDataContext {
/**
* Does this database support simple query to retrieve generated keys
* when the JDBC 3.0 feature is not supported
* when the JDBC 3.0 feature is not supported.
* {@link java.sql.DatabaseMetaData#supportsGetGeneratedKeys()}?
*/
public boolean isGetGeneratedKeysSimulated() {
......@@ -171,7 +172,7 @@ public class TableMetaDataContext {
/**
* Does this database support simple query to retrieve generated keys
* when the JDBC 3.0 feature is not supported
* when the JDBC 3.0 feature is not supported.
* {@link java.sql.DatabaseMetaData#supportsGetGeneratedKeys()}?
*/
public String getSimulationQueryForGetGeneratedKey(String tableName, String keyColumnName) {
......@@ -179,7 +180,7 @@ public class TableMetaDataContext {
}
/**
* Is a column name String array for retrieving generated keys supported
* Is a column name String array for retrieving generated keys supported?
* {@link java.sql.Connection#createStruct(String, Object[])}?
*/
public boolean isGeneratedKeysColumnNameArraySupported() {
......@@ -187,7 +188,7 @@ public class TableMetaDataContext {
}
/**
* Set {@link NativeJdbcExtractor} to be used to retrieve the native connection
* Set {@link NativeJdbcExtractor} to be used to retrieve the native connection.
*/
public void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor) {
this.nativeJdbcExtractor = nativeJdbcExtractor;
......@@ -195,7 +196,7 @@ public class TableMetaDataContext {
/**
* Process the current meta data with the provided configuration options
* Process the current meta data with the provided configuration options.
* @param dataSource the DataSource being used
* @param declaredColumns any columns that are declared
* @param generatedKeyNames name of generated keys
......@@ -212,7 +213,7 @@ public class TableMetaDataContext {
*/
protected List<String> reconcileColumnsToUse(List<String> declaredColumns, String[] generatedKeyNames) {
if (generatedKeyNames.length > 0) {
generatedKeyColumnsUsed = true;
this.generatedKeyColumnsUsed = true;
}
if (declaredColumns.size() > 0) {
return new ArrayList<String>(declaredColumns);
......@@ -240,7 +241,7 @@ public class TableMetaDataContext {
// database metadata is not necessarily providing case sensitive column names
Map caseInsensitiveParameterNames =
SqlParameterSourceUtils.extractCaseInsensitiveParameterNames(parameterSource);
for (String column : tableColumns) {
for (String column : this.tableColumns) {
if (parameterSource.hasValue(column)) {
values.add(SqlParameterSourceUtils.getTypedValue(parameterSource, column));
}
......@@ -280,7 +281,7 @@ public class TableMetaDataContext {
for (String key : inParameters.keySet()) {
source.put(key.toLowerCase(), inParameters.get(key));
}
for (String column : tableColumns) {
for (String column : this.tableColumns) {
values.add(source.get(column.toLowerCase()));
}
return values;
......@@ -316,7 +317,7 @@ public class TableMetaDataContext {
}
insertStatement.append(") VALUES(");
if (columnCount < 1) {
if (generatedKeyColumnsUsed) {
if (this.generatedKeyColumnsUsed) {
logger.info("Unable to locate non-key columns for table '" +
this.getTableName() + "' so an empty insert statement is generated");
}
......@@ -340,15 +341,12 @@ public class TableMetaDataContext {
* @return the array of types to be used
*/
public int[] createInsertTypes() {
int[] types = new int[this.getTableColumns().size()];
List<TableParameterMetaData> parameters = this.metaDataProvider.getTableParameterMetaData();
Map<String, TableParameterMetaData> parameterMap = new HashMap<String, TableParameterMetaData>(parameters.size());
for (TableParameterMetaData tpmd : parameters) {
parameterMap.put(tpmd.getParameterName().toUpperCase(), tpmd);
}
int typeIndx = 0;
for (String column : this.getTableColumns()) {
if (column == null) {
......@@ -365,7 +363,6 @@ public class TableMetaDataContext {
}
typeIndx++;
}
return types;
}
......
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2010 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.
......@@ -18,7 +18,6 @@ package org.springframework.jdbc.core.metadata;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
......@@ -38,74 +37,70 @@ import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
*/
public class TableMetaDataProviderFactory {
/** Logger */
private static final Log logger = LogFactory.getLog(TableMetaDataProviderFactory.class);
/**
* Create a TableMetaDataProvider based on the database metedata
* @param dataSource used to retrieve metedata
* @param context the class that holds configuration and metedata
* @return instance of the TableMetaDataProvider implementation to be used
*/
static public TableMetaDataProvider createMetaDataProvider(DataSource dataSource,
final TableMetaDataContext context) {
public static TableMetaDataProvider createMetaDataProvider(DataSource dataSource, TableMetaDataContext context) {
return createMetaDataProvider(dataSource, context, null);
}
/**
* Create a TableMetaDataProvider based on the database metedata
* @param dataSource used to retrieve metedata
* @param context the class that holds configuration and metedata
* @param nativeJdbcExtractor @{link NativeJdbcExtractor} to be used
* @param nativeJdbcExtractor the NativeJdbcExtractor to be used
* @return instance of the TableMetaDataProvider implementation to be used
*/
static public TableMetaDataProvider createMetaDataProvider(DataSource dataSource,
final TableMetaDataContext context,
final NativeJdbcExtractor nativeJdbcExtractor) {
public static TableMetaDataProvider createMetaDataProvider(DataSource dataSource,
final TableMetaDataContext context, final NativeJdbcExtractor nativeJdbcExtractor) {
try {
return (TableMetaDataProvider) JdbcUtils.extractDatabaseMetaData(
dataSource, new DatabaseMetaDataCallback() {
public Object processMetaData(DatabaseMetaData databaseMetaData)
throws SQLException, MetaDataAccessException {
String databaseProductName =
JdbcUtils.commonDatabaseName(databaseMetaData.getDatabaseProductName());
boolean accessTableColumnMetaData = context.isAccessTableColumnMetaData();
TableMetaDataProvider provider;
if ("Oracle".equals(databaseProductName)) {
provider = new OracleTableMetaDataProvider(databaseMetaData,
context.isOverrideIncludeSynonymsDefault());
}
else if ("HSQL Database Engine".equals(databaseProductName)) {
provider = new HsqlTableMetaDataProvider(databaseMetaData);
}
else if ("PostgreSQL".equals(databaseProductName)) {
provider = new PostgresTableMetaDataProvider(databaseMetaData);
}
else if ("Apache Derby".equals(databaseProductName)) {
provider = new DerbyTableMetaDataProvider(databaseMetaData);
}
else {
provider = new GenericTableMetaDataProvider(databaseMetaData);
}
if (nativeJdbcExtractor != null) {
provider.setNativeJdbcExtractor(nativeJdbcExtractor);
}
if (logger.isDebugEnabled()) {
logger.debug("Using " + provider.getClass().getName());
}
provider.initializeWithMetaData(databaseMetaData);
if (accessTableColumnMetaData) {
provider.initializeWithTableColumnMetaData(databaseMetaData, context.getCatalogName(),
context.getSchemaName(), context.getTableName());
}
return provider;
}
});
} catch (MetaDataAccessException e) {
throw new DataAccessResourceFailureException("Error retreiving database metadata", e);
return (TableMetaDataProvider) JdbcUtils.extractDatabaseMetaData(dataSource,
new DatabaseMetaDataCallback() {
public Object processMetaData(DatabaseMetaData databaseMetaData) throws SQLException {
String databaseProductName =
JdbcUtils.commonDatabaseName(databaseMetaData.getDatabaseProductName());
boolean accessTableColumnMetaData = context.isAccessTableColumnMetaData();
TableMetaDataProvider provider;
if ("Oracle".equals(databaseProductName)) {
provider = new OracleTableMetaDataProvider(databaseMetaData,
context.isOverrideIncludeSynonymsDefault());
}
else if ("HSQL Database Engine".equals(databaseProductName)) {
provider = new HsqlTableMetaDataProvider(databaseMetaData);
}
else if ("PostgreSQL".equals(databaseProductName)) {
provider = new PostgresTableMetaDataProvider(databaseMetaData);
}
else if ("Apache Derby".equals(databaseProductName)) {
provider = new DerbyTableMetaDataProvider(databaseMetaData);
}
else {
provider = new GenericTableMetaDataProvider(databaseMetaData);
}
if (nativeJdbcExtractor != null) {
provider.setNativeJdbcExtractor(nativeJdbcExtractor);
}
if (logger.isDebugEnabled()) {
logger.debug("Using " + provider.getClass().getSimpleName());
}
provider.initializeWithMetaData(databaseMetaData);
if (accessTableColumnMetaData) {
provider.initializeWithTableColumnMetaData(databaseMetaData, context.getCatalogName(),
context.getSchemaName(), context.getTableName());
}
return provider;
}
});
}
catch (MetaDataAccessException ex) {
throw new DataAccessResourceFailureException("Error retrieving database metadata", ex);
}
}
}
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2010 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.
......@@ -18,25 +18,24 @@ package org.springframework.jdbc.core.simple;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.ConnectionCallback;
import org.springframework.jdbc.core.JdbcTemplate;
......@@ -57,6 +56,7 @@ import org.springframework.util.Assert;
* This class provides the base SPI for {@link SimpleJdbcInsert}.
*
* @author Thomas Risberg
* @author Juergen Hoeller
* @since 2.5
*/
public abstract class AbstractJdbcInsert {
......@@ -65,10 +65,13 @@ public abstract class AbstractJdbcInsert {
protected final Log logger = LogFactory.getLog(getClass());
/** Lower-level class used to execute SQL */
private JdbcTemplate jdbcTemplate = new JdbcTemplate();
private final JdbcTemplate jdbcTemplate;
/** Context used to retrieve and manage database metadata */
private final TableMetaDataContext tableMetaDataContext = new TableMetaDataContext();
/** List of columns objects to be used in insert statement */
private List<String> declaredColumns = new ArrayList<String>();
private final List<String> declaredColumns = new ArrayList<String>();
/**
* Has this operation been compiled? Compilation means at
......@@ -77,31 +80,30 @@ public abstract class AbstractJdbcInsert {
*/
private boolean compiled = false;
/** the generated string used for insert statement */
/** The generated string used for insert statement */
private String insertString;
/** the SQL Type information for the insert columns */
/** The SQL type information for the insert columns */
private int[] insertTypes;
/** the names of the columns holding the generated key */
private String[] generatedKeyNames = new String[] {};
/** context used to retrieve and manage database metadata */
private TableMetaDataContext tableMetaDataContext = new TableMetaDataContext();
/** The names of the columns holding the generated key */
private String[] generatedKeyNames = new String[0];
/**
* Constructor for sublasses to delegate to for setting the DataSource.
*/
protected AbstractJdbcInsert(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
/**
* Constructor for sublasses to delegate to for setting the JdbcTemplate.
*/
protected AbstractJdbcInsert(JdbcTemplate jdbcTemplate) {
Assert.notNull(jdbcTemplate, "JdbcTemplate must not be null");
this.jdbcTemplate = jdbcTemplate;
setNativeJdbcExtractor(jdbcTemplate.getNativeJdbcExtractor());
}
......@@ -109,26 +111,19 @@ public abstract class AbstractJdbcInsert {
// Methods dealing with configuaration properties
//-------------------------------------------------------------------------
/**
* Get the name of the table for this insert
*/
public String getTableName() {
return tableMetaDataContext.getTableName();
}
/**
* Set the name of the table for this insert
*/
public void setTableName(String tableName) {
checkIfConfigurationModificationIsAllowed();
tableMetaDataContext.setTableName(tableName);
this.tableMetaDataContext.setTableName(tableName);
}
/**
* Get the name of the schema for this insert
* Get the name of the table for this insert
*/
public String getSchemaName() {
return tableMetaDataContext.getSchemaName();
public String getTableName() {
return this.tableMetaDataContext.getTableName();
}
/**
......@@ -136,14 +131,14 @@ public abstract class AbstractJdbcInsert {
*/
public void setSchemaName(String schemaName) {
checkIfConfigurationModificationIsAllowed();
tableMetaDataContext.setSchemaName(schemaName);
this.tableMetaDataContext.setSchemaName(schemaName);
}
/**
* Get the name of the catalog for this insert
* Get the name of the schema for this insert
*/
public String getCatalogName() {
return tableMetaDataContext.getCatalogName();
public String getSchemaName() {
return this.tableMetaDataContext.getSchemaName();
}
/**
......@@ -151,7 +146,14 @@ public abstract class AbstractJdbcInsert {
*/
public void setCatalogName(String catalogName) {
checkIfConfigurationModificationIsAllowed();
tableMetaDataContext.setCatalogName(catalogName);
this.tableMetaDataContext.setCatalogName(catalogName);
}
/**
* Get the name of the catalog for this insert
*/
public String getCatalogName() {
return this.tableMetaDataContext.getCatalogName();
}
/**
......@@ -159,22 +161,22 @@ public abstract class AbstractJdbcInsert {
*/
public void setColumnNames(List<String> columnNames) {
checkIfConfigurationModificationIsAllowed();
declaredColumns.clear();
declaredColumns.addAll(columnNames);
this.declaredColumns.clear();
this.declaredColumns.addAll(columnNames);
}
/**
* Get the names of the columns used
*/
public List<String> getColumnNames() {
return Collections.unmodifiableList(declaredColumns);
return Collections.unmodifiableList(this.declaredColumns);
}
/**
* Get the names of any generated keys
*/
public String[] getGeneratedKeyNames() {
return generatedKeyNames;
return this.generatedKeyNames;
}
/**
......@@ -207,32 +209,32 @@ public abstract class AbstractJdbcInsert {
this.tableMetaDataContext.setOverrideIncludeSynonymsDefault(override);
}
/**
* Set the {@link NativeJdbcExtractor} to use to retrieve the native connection if necessary
*/
public void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor) {
this.tableMetaDataContext.setNativeJdbcExtractor(nativeJdbcExtractor);
}
/**
* Get the insert string to be used
*/
public String getInsertString() {
return insertString;
return this.insertString;
}
/**
* Get the array of {@link java.sql.Types} to be used for insert
*/
public int[] getInsertTypes() {
return insertTypes;
return this.insertTypes;
}
/**
* Get the {@link JdbcTemplate} that is configured to be used
*/
protected JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
/**
* Set the {@link NativeJdbcExtractor} to use to retrieve the native connection if necessary
*/
public void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor) {
this.tableMetaDataContext.setNativeJdbcExtractor(nativeJdbcExtractor);
return this.jdbcTemplate;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册