Skip to content

Commit eec4a6d

Browse files
committed
Retry DatabaseMetaData retrieval if access to transactional connection fails
Closes gh-25681
1 parent a577f63 commit eec4a6d

File tree

1 file changed

+27
-13
lines changed
  • spring-jdbc/src/main/java/org/springframework/jdbc/support

1 file changed

+27
-13
lines changed

spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcUtils.java

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -305,30 +305,44 @@ else if (obj instanceof java.sql.Date) {
305305

306306
/**
307307
* Extract database meta-data via the given DatabaseMetaDataCallback.
308-
* <p>This method will open a connection to the database and retrieve the database meta-data.
309-
* Since this method is called before the exception translation feature is configured for
310-
* a datasource, this method can not rely on the SQLException translation functionality.
311-
* <p>Any exceptions will be wrapped in a MetaDataAccessException. This is a checked exception
312-
* and any calling code should catch and handle this exception. You can just log the
313-
* error and hope for the best, but there is probably a more serious error that will
314-
* reappear when you try to access the database again.
308+
* <p>This method will open a connection to the database and retrieve its meta-data.
309+
* Since this method is called before the exception translation feature is configured
310+
* for a DataSource, this method can not rely on SQLException translation itself.
311+
* <p>Any exceptions will be wrapped in a MetaDataAccessException. This is a checked
312+
* exception and any calling code should catch and handle this exception. You can just
313+
* log the error and hope for the best, but there is probably a more serious error that
314+
* will reappear when you try to access the database again.
315315
* @param dataSource the DataSource to extract meta-data for
316316
* @param action callback that will do the actual work
317317
* @return object containing the extracted information, as returned by
318318
* the DatabaseMetaDataCallback's {@code processMetaData} method
319319
* @throws MetaDataAccessException if meta-data access failed
320+
* @see java.sql.DatabaseMetaData
320321
*/
321322
public static Object extractDatabaseMetaData(DataSource dataSource, DatabaseMetaDataCallback action)
322323
throws MetaDataAccessException {
323324

324325
Connection con = null;
325326
try {
326327
con = DataSourceUtils.getConnection(dataSource);
327-
if (con == null) {
328-
// should only happen in test environments
329-
throw new MetaDataAccessException("Connection returned by DataSource [" + dataSource + "] was null");
328+
DatabaseMetaData metaData;
329+
try {
330+
metaData = con.getMetaData();
331+
}
332+
catch (SQLException ex) {
333+
if (DataSourceUtils.isConnectionTransactional(con, dataSource)) {
334+
// Probably a closed thread-bound Connection - retry against fresh Connection
335+
DataSourceUtils.releaseConnection(con, dataSource);
336+
con = null;
337+
logger.debug("Failed to obtain DatabaseMetaData from transactional Connection - " +
338+
"retrying against fresh Connection", ex);
339+
con = dataSource.getConnection();
340+
metaData = con.getMetaData();
341+
}
342+
else {
343+
throw ex;
344+
}
330345
}
331-
DatabaseMetaData metaData = con.getMetaData();
332346
if (metaData == null) {
333347
// should only happen in test environments
334348
throw new MetaDataAccessException("DatabaseMetaData returned by Connection [" + con + "] was null");
@@ -458,9 +472,9 @@ public static boolean isNumeric(int sqlType) {
458472
* expressed in the JDBC 4.0 specification:
459473
* <p><i>columnLabel - the label for the column specified with the SQL AS clause.
460474
* If the SQL AS clause was not specified, then the label is the name of the column</i>.
461-
* @return the column name to use
462475
* @param resultSetMetaData the current meta-data to use
463476
* @param columnIndex the index of the column for the look up
477+
* @return the column name to use
464478
* @throws SQLException in case of lookup failure
465479
*/
466480
public static String lookupColumnName(ResultSetMetaData resultSetMetaData, int columnIndex) throws SQLException {

0 commit comments

Comments
 (0)