Sync with 3.1.x
* 3.1.x: (61 commits) Compensate for changes in JDK 7 Introspector Avoid 'type mismatch' errors in ExtendedBeanInfo Polish ExtendedBeanInfo and tests Infer AnnotationAttributes method return types Minor fix in MVC reference doc chapter Hibernate 4.1 etc TypeDescriptor equals implementation accepts annotations in any order "setBasenames" uses varargs now (for programmatic setup; SPR-9106) @ActiveProfiles mechanism works with @ImportResource as well (SPR-8992 polishing clarified Resource's "getFilename" method to consistently return null substituteNamedParameters detects and unwraps SqlParameterValue object Replace spaces with tabs Consider security in ClassUtils#getMostSpecificMethod Adding null check for username being null. Improvements for registering custom SQL exception translators in app c SPR-7680 Adding QueryTimeoutException to the DataAccessException hiera Minor polish in WebMvcConfigurationSupport Detect overridden boolean getters in ExtendedBeanInfo Polish ExtendedBeanInfoTests ...
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -181,8 +181,13 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
|
||||
setGeneratedKeysColumnNameArraySupported(false);
|
||||
}
|
||||
else {
|
||||
logger.debug("GeneratedKeysColumnNameArray is supported for " + databaseProductName);
|
||||
setGeneratedKeysColumnNameArraySupported(true);
|
||||
if (isGetGeneratedKeysSupported()) {
|
||||
logger.debug("GeneratedKeysColumnNameArray is supported for " + databaseProductName);
|
||||
setGeneratedKeysColumnNameArraySupported(true);
|
||||
}
|
||||
else {
|
||||
setGeneratedKeysColumnNameArraySupported(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SQLException se) {
|
||||
@@ -307,7 +312,7 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
|
||||
tmd.setTableName(tables.getString("TABLE_NAME"));
|
||||
tmd.setType(tables.getString("TABLE_TYPE"));
|
||||
if (tmd.getSchemaName() == null) {
|
||||
tableMeta.put(userName.toUpperCase(), tmd);
|
||||
tableMeta.put(userName != null ? userName.toUpperCase() : "", tmd);
|
||||
}
|
||||
else {
|
||||
tableMeta.put(tmd.getSchemaName().toUpperCase(), tmd);
|
||||
@@ -335,7 +340,7 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
|
||||
if (schemaName == null) {
|
||||
tmd = tableMeta.get(getDefaultSchema());
|
||||
if (tmd == null) {
|
||||
tmd = tableMeta.get(userName.toUpperCase());
|
||||
tmd = tableMeta.get(userName != null ? userName.toUpperCase() : "");
|
||||
}
|
||||
if (tmd == null) {
|
||||
tmd = tableMeta.get("PUBLIC");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -85,12 +85,18 @@ public abstract class NamedParameterUtils {
|
||||
int escapes = 0;
|
||||
int i = 0;
|
||||
while (i < statement.length) {
|
||||
int skipToPosition = skipCommentsAndQuotes(statement, i);
|
||||
if (i != skipToPosition) {
|
||||
if (skipToPosition >= statement.length) {
|
||||
int skipToPosition = i;
|
||||
while (i < statement.length) {
|
||||
skipToPosition = skipCommentsAndQuotes(statement, i);
|
||||
if (i == skipToPosition) {
|
||||
break;
|
||||
}
|
||||
i = skipToPosition;
|
||||
else {
|
||||
i = skipToPosition;
|
||||
}
|
||||
}
|
||||
if (i >= statement.length) {
|
||||
break;
|
||||
}
|
||||
char c = statement[i];
|
||||
if (c == ':' || c == '&') {
|
||||
@@ -252,6 +258,9 @@ public abstract class NamedParameterUtils {
|
||||
actualSql.append(originalSql.substring(lastIndex, startIndex));
|
||||
if (paramSource != null && paramSource.hasValue(paramName)) {
|
||||
Object value = paramSource.getValue(paramName);
|
||||
if (value instanceof SqlParameterValue) {
|
||||
value = ((SqlParameterValue) value).getValue();
|
||||
}
|
||||
if (value instanceof Collection) {
|
||||
Iterator entryIter = ((Collection) value).iterator();
|
||||
int k = 0;
|
||||
|
||||
@@ -181,9 +181,10 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
|
||||
for (String statement : statements) {
|
||||
lineNumber++;
|
||||
try {
|
||||
int rowsAffected = stmt.executeUpdate(statement);
|
||||
stmt.execute(statement);
|
||||
int rowsAffected = stmt.getUpdateCount();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(rowsAffected + " rows affected by SQL: " + statement);
|
||||
logger.debug(rowsAffected + " returned as updateCount for SQL: " + statement);
|
||||
}
|
||||
}
|
||||
catch (SQLException ex) {
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.jdbc.support;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* Registry for registering custom {@link org.springframework.jdbc.support.SQLExceptionTranslator}.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @since 3.1
|
||||
*/
|
||||
public class CustomSQLExceptionTranslatorRegistrar implements InitializingBean {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(CustomSQLExceptionTranslatorRegistrar.class);
|
||||
|
||||
/**
|
||||
* Map registry to hold custom translators specific databases.
|
||||
* Key is the database product name as defined in the
|
||||
* {@link org.springframework.jdbc.support.SQLErrorCodesFactory}.
|
||||
*/
|
||||
private final Map<String, SQLExceptionTranslator> sqlExceptionTranslators =
|
||||
new HashMap<String, SQLExceptionTranslator>();
|
||||
|
||||
/**
|
||||
* Setter for a Map of translators where the key must be the database name as defined in the
|
||||
* sql-error-codes.xml file. This method is used when this registry is used in an application context.
|
||||
* <p>Note that any existing translators will remain unless there is a match in the database name at which
|
||||
* point the new translator will replace the existing one.
|
||||
*
|
||||
* @param sqlExceptionTranslators
|
||||
*/
|
||||
public void setSqlExceptionTranslators(Map<String, SQLExceptionTranslator> sqlExceptionTranslators) {
|
||||
this.sqlExceptionTranslators.putAll(sqlExceptionTranslators);
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Registering custom SQL exception translators for database(s): " +
|
||||
sqlExceptionTranslators.keySet());
|
||||
}
|
||||
for (String dbName : sqlExceptionTranslators.keySet()) {
|
||||
CustomSQLExceptionTranslatorRegistry.getInstance()
|
||||
.registerSqlExceptionTranslator(dbName, sqlExceptionTranslators.get(dbName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.jdbc.support;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
|
||||
/**
|
||||
* Registry for custom {@link org.springframework.jdbc.support.SQLExceptionTranslator} instances associated with
|
||||
* specific databases allowing for overriding translation based on values contained in the configuration file
|
||||
* named "sql-error-codes.xml".
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @since 3.1
|
||||
* @see SQLErrorCodesFactory
|
||||
*/
|
||||
public class CustomSQLExceptionTranslatorRegistry {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(CustomSQLExceptionTranslatorRegistry.class);
|
||||
|
||||
/**
|
||||
* Map registry to hold custom translators specific databases.
|
||||
* Key is the database product name as defined in the
|
||||
* {@link org.springframework.jdbc.support.SQLErrorCodesFactory}.
|
||||
*/
|
||||
private final Map<String, SQLExceptionTranslator> sqlExceptionTranslatorRegistry =
|
||||
new HashMap<String, SQLExceptionTranslator>();
|
||||
|
||||
|
||||
/**
|
||||
* Keep track of a single instance so we can return it to classes that request it.
|
||||
*/
|
||||
private static final CustomSQLExceptionTranslatorRegistry instance = new CustomSQLExceptionTranslatorRegistry();
|
||||
|
||||
|
||||
/**
|
||||
* Return the singleton instance.
|
||||
*/
|
||||
public static CustomSQLExceptionTranslatorRegistry getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance of the {@link org.springframework.jdbc.support.CustomSQLExceptionTranslatorRegistry} class.
|
||||
* <p>Not public to enforce Singleton design pattern.
|
||||
*/
|
||||
private CustomSQLExceptionTranslatorRegistry() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new custom translator for the specified database name.
|
||||
*
|
||||
* @param dbName the database name
|
||||
* @param sqlExceptionTranslator the custom translator
|
||||
*/
|
||||
public void registerSqlExceptionTranslator(String dbName, SQLExceptionTranslator sqlExceptionTranslator) {
|
||||
SQLExceptionTranslator replaced = sqlExceptionTranslatorRegistry.put(dbName, sqlExceptionTranslator);
|
||||
if (replaced != null) {
|
||||
logger.warn("Replacing custom translator '" + replaced +
|
||||
"' for database " + dbName +
|
||||
" with '" + sqlExceptionTranslator + "'");
|
||||
}
|
||||
else {
|
||||
logger.info("Adding custom translator '" + sqlExceptionTranslator.getClass().getSimpleName() +
|
||||
"' for database " + dbName);
|
||||
}
|
||||
}
|
||||
|
||||
public SQLExceptionTranslator findSqlExceptionTranslatorForDatabase(String dbName) {
|
||||
return sqlExceptionTranslatorRegistry.get(dbName);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -104,6 +104,10 @@ public class SQLErrorCodes {
|
||||
return customSqlExceptionTranslator;
|
||||
}
|
||||
|
||||
public void setCustomSqlExceptionTranslator(SQLExceptionTranslator customSqlExceptionTranslator) {
|
||||
this.customSqlExceptionTranslator = customSqlExceptionTranslator;
|
||||
}
|
||||
|
||||
public void setCustomSqlExceptionTranslatorClass(Class customSqlExceptionTranslatorClass) {
|
||||
if (customSqlExceptionTranslatorClass != null) {
|
||||
try {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2012 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,6 +17,7 @@
|
||||
package org.springframework.jdbc.support;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import javax.sql.DataSource;
|
||||
@@ -130,7 +131,7 @@ public class SQLErrorCodesFactory {
|
||||
logger.warn("Error loading SQL error codes from config file", ex);
|
||||
errorCodes = Collections.emptyMap();
|
||||
}
|
||||
|
||||
|
||||
this.errorCodesMap = errorCodes;
|
||||
}
|
||||
|
||||
@@ -159,7 +160,7 @@ public class SQLErrorCodesFactory {
|
||||
*/
|
||||
public SQLErrorCodes getErrorCodes(String dbName) {
|
||||
Assert.notNull(dbName, "Database product name must not be null");
|
||||
|
||||
|
||||
SQLErrorCodes sec = this.errorCodesMap.get(dbName);
|
||||
if (sec == null) {
|
||||
for (SQLErrorCodes candidate : this.errorCodesMap.values()) {
|
||||
@@ -170,6 +171,7 @@ public class SQLErrorCodesFactory {
|
||||
}
|
||||
}
|
||||
if (sec != null) {
|
||||
checkSqlExceptionTranslatorRegistry(dbName, sec);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("SQL error codes for '" + dbName + "' found");
|
||||
}
|
||||
@@ -246,4 +248,24 @@ public class SQLErrorCodesFactory {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkSqlExceptionTranslatorRegistry(String dbName, SQLErrorCodes dbCodes) {
|
||||
// Check the custom sql exception translator registry for any entries
|
||||
SQLExceptionTranslator customTranslator =
|
||||
CustomSQLExceptionTranslatorRegistry.getInstance().findSqlExceptionTranslatorForDatabase(dbName);
|
||||
if (customTranslator != null) {
|
||||
if (dbCodes.getCustomSqlExceptionTranslator() != null) {
|
||||
logger.warn("Overriding already defined custom translator '" +
|
||||
dbCodes.getCustomSqlExceptionTranslator().getClass().getSimpleName() +
|
||||
" with '" + customTranslator.getClass().getSimpleName() +
|
||||
"' found in the CustomSQLExceptionTranslatorRegistry for database " + dbName);
|
||||
}
|
||||
else {
|
||||
logger.info("Using custom translator '" + customTranslator.getClass().getSimpleName() +
|
||||
"' found in the CustomSQLExceptionTranslatorRegistry for database " + dbName);
|
||||
}
|
||||
dbCodes.setCustomSqlExceptionTranslator(customTranslator);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user