001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.dbcp2; 018 019import java.sql.Connection; 020import java.sql.SQLException; 021import java.sql.Statement; 022import java.time.Duration; 023import java.util.Collection; 024import java.util.Objects; 025import java.util.concurrent.atomic.AtomicLong; 026 027import javax.management.MalformedObjectNameException; 028import javax.management.ObjectName; 029 030import org.apache.commons.logging.Log; 031import org.apache.commons.logging.LogFactory; 032import org.apache.commons.pool2.DestroyMode; 033import org.apache.commons.pool2.KeyedObjectPool; 034import org.apache.commons.pool2.ObjectPool; 035import org.apache.commons.pool2.PooledObject; 036import org.apache.commons.pool2.PooledObjectFactory; 037import org.apache.commons.pool2.impl.DefaultPooledObject; 038import org.apache.commons.pool2.impl.GenericKeyedObjectPool; 039import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; 040 041/** 042 * A {@link PooledObjectFactory} that creates {@link PoolableConnection}s. 043 * 044 * @since 2.0 045 */ 046public class PoolableConnectionFactory implements PooledObjectFactory<PoolableConnection> { 047 048 private static final Log log = LogFactory.getLog(PoolableConnectionFactory.class); 049 050 /** 051 * Internal constant to indicate the level is not set. 052 */ 053 static final int UNKNOWN_TRANSACTION_ISOLATION = -1; 054 055 private final ConnectionFactory connectionFactory; 056 057 private final ObjectName dataSourceJmxObjectName; 058 059 private volatile String validationQuery; 060 061 private volatile Duration validationQueryTimeoutDuration = Duration.ofSeconds(-1); 062 063 private Collection<String> connectionInitSqls; 064 065 private Collection<String> disconnectionSqlCodes; 066 067 private boolean fastFailValidation = true; 068 069 private volatile ObjectPool<PoolableConnection> pool; 070 071 private Boolean defaultReadOnly; 072 073 private Boolean defaultAutoCommit; 074 075 private boolean autoCommitOnReturn = true; 076 077 private boolean rollbackOnReturn = true; 078 079 private int defaultTransactionIsolation = UNKNOWN_TRANSACTION_ISOLATION; 080 081 private String defaultCatalog; 082 083 private String defaultSchema; 084 085 private boolean cacheState; 086 087 private boolean poolStatements; 088 089 private boolean clearStatementPoolOnReturn; 090 091 private int maxOpenPreparedStatements = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY; 092 093 private Duration maxConnDuration = Duration.ofMillis(-1); 094 095 private final AtomicLong connectionIndex = new AtomicLong(); 096 097 private Duration defaultQueryTimeoutDuration; 098 099 /** 100 * Creates a new {@code PoolableConnectionFactory}. 101 * 102 * @param connFactory 103 * the {@link ConnectionFactory} from which to obtain base {@link Connection}s 104 * @param dataSourceJmxObjectName 105 * The JMX object name, may be null. 106 */ 107 public PoolableConnectionFactory(final ConnectionFactory connFactory, final ObjectName dataSourceJmxObjectName) { 108 this.connectionFactory = connFactory; 109 this.dataSourceJmxObjectName = dataSourceJmxObjectName; 110 } 111 112 @Override 113 public void activateObject(final PooledObject<PoolableConnection> p) throws SQLException { 114 115 validateLifetime(p); 116 117 final PoolableConnection pConnection = p.getObject(); 118 pConnection.activate(); 119 120 if (defaultAutoCommit != null && pConnection.getAutoCommit() != defaultAutoCommit) { 121 pConnection.setAutoCommit(defaultAutoCommit); 122 } 123 if (defaultTransactionIsolation != UNKNOWN_TRANSACTION_ISOLATION 124 && pConnection.getTransactionIsolation() != defaultTransactionIsolation) { 125 pConnection.setTransactionIsolation(defaultTransactionIsolation); 126 } 127 if (defaultReadOnly != null && pConnection.isReadOnly() != defaultReadOnly) { 128 pConnection.setReadOnly(defaultReadOnly); 129 } 130 if (defaultCatalog != null && !defaultCatalog.equals(pConnection.getCatalog())) { 131 pConnection.setCatalog(defaultCatalog); 132 } 133 if (defaultSchema != null && !defaultSchema.equals(Jdbc41Bridge.getSchema(pConnection))) { 134 Jdbc41Bridge.setSchema(pConnection, defaultSchema); 135 } 136 pConnection.setDefaultQueryTimeout(defaultQueryTimeoutDuration); 137 } 138 139 @Override 140 public void destroyObject(final PooledObject<PoolableConnection> p) throws SQLException { 141 p.getObject().reallyClose(); 142 } 143 144 /** 145 * @since 2.9.0 146 */ 147 @Override 148 public void destroyObject(final PooledObject<PoolableConnection> p, final DestroyMode mode) throws SQLException { 149 if (mode == DestroyMode.ABANDONED) { 150 p.getObject().getInnermostDelegate().abort(Runnable::run); 151 } else { 152 p.getObject().reallyClose(); 153 } 154 } 155 156 /** 157 * Gets the cache state. 158 * 159 * @return The cache state. 160 * @since 2.6.0. 161 */ 162 public boolean getCacheState() { 163 return cacheState; 164 } 165 166 /** 167 * Gets the connection factory. 168 * 169 * @return The connection factory. 170 * @since 2.6.0. 171 */ 172 public ConnectionFactory getConnectionFactory() { 173 return connectionFactory; 174 } 175 176 protected AtomicLong getConnectionIndex() { 177 return connectionIndex; 178 } 179 180 /** 181 * @return The collection of initialization SQL statements. 182 * @since 2.6.0 183 */ 184 public Collection<String> getConnectionInitSqls() { 185 return connectionInitSqls; 186 } 187 188 /** 189 * @return The data source JMX ObjectName 190 * @since 2.6.0. 191 */ 192 public ObjectName getDataSourceJmxName() { 193 return dataSourceJmxObjectName; 194 } 195 196 /** 197 * @return The data source JMS ObjectName. 198 * @since 2.6.0 199 */ 200 public ObjectName getDataSourceJmxObjectName() { 201 return dataSourceJmxObjectName; 202 } 203 204 /** 205 * @return Default auto-commit value. 206 * @since 2.6.0 207 */ 208 public Boolean getDefaultAutoCommit() { 209 return defaultAutoCommit; 210 } 211 212 /** 213 * @return Default catalog. 214 * @since 2.6.0 215 */ 216 public String getDefaultCatalog() { 217 return defaultCatalog; 218 } 219 220 /** 221 * @return Default query timeout in seconds. 222 * @deprecated Use {@link #getDefaultQueryTimeoutDuration()}. 223 */ 224 @Deprecated 225 public Integer getDefaultQueryTimeout() { 226 return getDefaultQueryTimeoutSeconds(); 227 } 228 229 /** 230 * Gets the default query timeout Duration. 231 * 232 * @return Default query timeout Duration. 233 * @since 2.10.0 234 */ 235 public Duration getDefaultQueryTimeoutDuration() { 236 return defaultQueryTimeoutDuration; 237 } 238 239 /** 240 * @return Default query timeout in seconds. 241 * @since 2.6.0 242 * @deprecated Use {@link #getDefaultQueryTimeoutDuration()}. 243 */ 244 @Deprecated 245 public Integer getDefaultQueryTimeoutSeconds() { 246 return defaultQueryTimeoutDuration == null ? null : (int) defaultQueryTimeoutDuration.getSeconds(); 247 } 248 249 /** 250 * @return Default read-only-value. 251 * @since 2.6.0 252 */ 253 public Boolean getDefaultReadOnly() { 254 return defaultReadOnly; 255 } 256 257 /** 258 * @return Default schema. 259 * @since 2.6.0 260 */ 261 public String getDefaultSchema() { 262 return defaultSchema; 263 } 264 265 /** 266 * @return Default transaction isolation. 267 * @since 2.6.0 268 */ 269 public int getDefaultTransactionIsolation() { 270 return defaultTransactionIsolation; 271 } 272 273 /** 274 * SQL_STATE codes considered to signal fatal conditions. 275 * <p> 276 * Overrides the defaults in {@link Utils#getDisconnectionSqlCodes()} (plus anything starting with 277 * {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). If this property is non-null and {@link #isFastFailValidation()} is 278 * {@code true}, whenever connections created by this factory generate exceptions with SQL_STATE codes in this list, 279 * they will be marked as "fatally disconnected" and subsequent validations will fail fast (no attempt at isValid or 280 * validation query). 281 * </p> 282 * <p> 283 * If {@link #isFastFailValidation()} is {@code false} setting this property has no effect. 284 * </p> 285 * 286 * @return SQL_STATE codes overriding defaults 287 * @since 2.1 288 */ 289 public Collection<String> getDisconnectionSqlCodes() { 290 return disconnectionSqlCodes; 291 } 292 293 /** 294 * Gets the Maximum connection duration. 295 * 296 * @return Maximum connection duration. 297 * @since 2.10.0 298 */ 299 public Duration getMaxConnDuration() { 300 return maxConnDuration; 301 } 302 303 /** 304 * Gets the Maximum connection lifetime in milliseconds. 305 * 306 * @return Maximum connection lifetime in milliseconds. 307 * @since 2.6.0 308 */ 309 public long getMaxConnLifetimeMillis() { 310 return maxConnDuration.toMillis(); 311 } 312 313 protected int getMaxOpenPreparedStatements() { 314 return maxOpenPreparedStatements; 315 } 316 /** 317 * Returns the {@link ObjectPool} in which {@link Connection}s are pooled. 318 * 319 * @return the connection pool 320 */ 321 public synchronized ObjectPool<PoolableConnection> getPool() { 322 return pool; 323 } 324 /** 325 * @return Whether to pool statements. 326 * @since 2.6.0. 327 */ 328 public boolean getPoolStatements() { 329 return poolStatements; 330 } 331 /** 332 * @return Validation query. 333 * @since 2.6.0 334 */ 335 public String getValidationQuery() { 336 return validationQuery; 337 } 338 339 /** 340 * Gets the query timeout in seconds. 341 * 342 * @return Validation query timeout in seconds. 343 * @since 2.10.0 344 */ 345 public Duration getValidationQueryTimeoutDuration() { 346 return validationQueryTimeoutDuration; 347 } 348 349 /** 350 * Gets the query timeout in seconds. 351 * 352 * @return Validation query timeout in seconds. 353 * @since 2.6.0 354 * @deprecated Use {@link #getValidationQueryTimeoutDuration()}. 355 */ 356 @Deprecated 357 public int getValidationQueryTimeoutSeconds() { 358 return (int) validationQueryTimeoutDuration.getSeconds(); 359 } 360 361 protected void initializeConnection(final Connection conn) throws SQLException { 362 final Collection<String> sqls = connectionInitSqls; 363 if (conn.isClosed()) { 364 throw new SQLException("initializeConnection: connection closed"); 365 } 366 if (!Utils.isEmpty(sqls)) { 367 try (Statement statement = conn.createStatement()) { 368 for (final String sql : sqls) { 369 statement.execute(Objects.requireNonNull(sql, "null connectionInitSqls element")); 370 } 371 } 372 } 373 } 374 375 /** 376 * @return Whether to auto-commit on return. 377 * @since 2.6.0 378 */ 379 public boolean isAutoCommitOnReturn() { 380 return autoCommitOnReturn; 381 } 382 383 /** 384 * @return Whether to auto-commit on return. 385 * @deprecated Use {@link #isAutoCommitOnReturn()}. 386 */ 387 @Deprecated 388 public boolean isEnableAutoCommitOnReturn() { 389 return autoCommitOnReturn; 390 } 391 392 /** 393 * True means that validation will fail immediately for connections that have previously thrown SQLExceptions with 394 * SQL_STATE indicating fatal disconnection errors. 395 * 396 * @return true if connections created by this factory will fast fail validation. 397 * @see #setDisconnectionSqlCodes(Collection) 398 * @since 2.1 399 * @since 2.5.0 Defaults to true, previous versions defaulted to false. 400 */ 401 public boolean isFastFailValidation() { 402 return fastFailValidation; 403 } 404 405 /** 406 * @return Whether to rollback on return. 407 */ 408 public boolean isRollbackOnReturn() { 409 return rollbackOnReturn; 410 } 411 412 @Override 413 public PooledObject<PoolableConnection> makeObject() throws SQLException { 414 Connection conn = connectionFactory.createConnection(); 415 if (conn == null) { 416 throw new IllegalStateException("Connection factory returned null from createConnection"); 417 } 418 try { 419 initializeConnection(conn); 420 } catch (final SQLException e) { 421 // Make sure the connection is closed 422 Utils.closeQuietly((AutoCloseable) conn); 423 // Rethrow original exception so it is visible to caller 424 throw e; 425 } 426 427 final long connIndex = connectionIndex.getAndIncrement(); 428 429 if (poolStatements) { 430 conn = new PoolingConnection(conn); 431 final GenericKeyedObjectPoolConfig<DelegatingPreparedStatement> config = new GenericKeyedObjectPoolConfig<>(); 432 config.setMaxTotalPerKey(-1); 433 config.setBlockWhenExhausted(false); 434 config.setMaxWait(Duration.ZERO); 435 config.setMaxIdlePerKey(1); 436 config.setMaxTotal(maxOpenPreparedStatements); 437 if (dataSourceJmxObjectName != null) { 438 final StringBuilder base = new StringBuilder(dataSourceJmxObjectName.toString()); 439 base.append(Constants.JMX_CONNECTION_BASE_EXT); 440 base.append(connIndex); 441 config.setJmxNameBase(base.toString()); 442 config.setJmxNamePrefix(Constants.JMX_STATEMENT_POOL_PREFIX); 443 } else { 444 config.setJmxEnabled(false); 445 } 446 final PoolingConnection poolingConn = (PoolingConnection) conn; 447 final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> stmtPool = new GenericKeyedObjectPool<>(poolingConn, config); 448 poolingConn.setStatementPool(stmtPool); 449 poolingConn.setClearStatementPoolOnReturn(clearStatementPoolOnReturn); 450 poolingConn.setCacheState(cacheState); 451 } 452 453 // Register this connection with JMX 454 final ObjectName connJmxName; 455 if (dataSourceJmxObjectName == null) { 456 connJmxName = null; 457 } else { 458 final String name = dataSourceJmxObjectName.toString() + Constants.JMX_CONNECTION_BASE_EXT + connIndex; 459 try { 460 connJmxName = new ObjectName(name); 461 } catch (final MalformedObjectNameException e) { 462 Utils.closeQuietly((AutoCloseable) conn); 463 throw new SQLException(name, e); 464 } 465 } 466 467 final PoolableConnection pc = new PoolableConnection(conn, pool, connJmxName, disconnectionSqlCodes, fastFailValidation); 468 pc.setCacheState(cacheState); 469 470 return new DefaultPooledObject<>(pc); 471 } 472 473 @Override 474 public void passivateObject(final PooledObject<PoolableConnection> p) throws SQLException { 475 476 validateLifetime(p); 477 478 final PoolableConnection conn = p.getObject(); 479 Boolean connAutoCommit = null; 480 if (rollbackOnReturn) { 481 connAutoCommit = conn.getAutoCommit(); 482 if (!connAutoCommit && !conn.isReadOnly()) { 483 conn.rollback(); 484 } 485 } 486 487 conn.clearWarnings(); 488 489 // DBCP-97 / DBCP-399 / DBCP-351 Idle connections in the pool should 490 // have autoCommit enabled 491 if (autoCommitOnReturn) { 492 if (connAutoCommit == null) { 493 connAutoCommit = conn.getAutoCommit(); 494 } 495 if (!connAutoCommit) { 496 conn.setAutoCommit(true); 497 } 498 } 499 500 conn.passivate(); 501 } 502 503 public void setAutoCommitOnReturn(final boolean autoCommitOnReturn) { 504 this.autoCommitOnReturn = autoCommitOnReturn; 505 } 506 507 public void setCacheState(final boolean cacheState) { 508 this.cacheState = cacheState; 509 } 510 511 /** 512 * Sets whether the pool of statements (which was enabled with {@link #setPoolStatements(boolean)}) should 513 * be cleared when the connection is returned to its pool. Default is false. 514 * 515 * @param clearStatementPoolOnReturn clear or not 516 * @since 2.8.0 517 */ 518 public void setClearStatementPoolOnReturn(final boolean clearStatementPoolOnReturn) { 519 this.clearStatementPoolOnReturn = clearStatementPoolOnReturn; 520 } 521 522 /** 523 * Sets the SQL statements I use to initialize newly created {@link Connection}s. Using {@code null} turns off 524 * connection initialization. 525 * 526 * @param connectionInitSqls 527 * SQL statement to initialize {@link Connection}s. 528 */ 529 public void setConnectionInitSql(final Collection<String> connectionInitSqls) { 530 this.connectionInitSqls = connectionInitSqls; 531 } 532 /** 533 * Sets the default "auto commit" setting for borrowed {@link Connection}s 534 * 535 * @param defaultAutoCommit 536 * the default "auto commit" setting for borrowed {@link Connection}s 537 */ 538 public void setDefaultAutoCommit(final Boolean defaultAutoCommit) { 539 this.defaultAutoCommit = defaultAutoCommit; 540 } 541 542 /** 543 * Sets the default "catalog" setting for borrowed {@link Connection}s 544 * 545 * @param defaultCatalog 546 * the default "catalog" setting for borrowed {@link Connection}s 547 */ 548 public void setDefaultCatalog(final String defaultCatalog) { 549 this.defaultCatalog = defaultCatalog; 550 } 551 552 /** 553 * Sets the query timeout Duration. 554 * 555 * @param defaultQueryTimeoutDuration the query timeout Duration. 556 * @since 2.10.0 557 */ 558 public void setDefaultQueryTimeout(final Duration defaultQueryTimeoutDuration) { 559 this.defaultQueryTimeoutDuration = defaultQueryTimeoutDuration; 560 } 561 562 /** 563 * Sets the query timeout in seconds. 564 * 565 * @param defaultQueryTimeoutSeconds the query timeout in seconds. 566 * @deprecated Use {@link #setDefaultQueryTimeout(Duration)}. 567 */ 568 @Deprecated 569 public void setDefaultQueryTimeout(final Integer defaultQueryTimeoutSeconds) { 570 this.defaultQueryTimeoutDuration = defaultQueryTimeoutSeconds == null ? null : Duration.ofSeconds(defaultQueryTimeoutSeconds); 571 } 572 573 /** 574 * Sets the default "read only" setting for borrowed {@link Connection}s 575 * 576 * @param defaultReadOnly 577 * the default "read only" setting for borrowed {@link Connection}s 578 */ 579 public void setDefaultReadOnly(final Boolean defaultReadOnly) { 580 this.defaultReadOnly = defaultReadOnly; 581 } 582 583 /** 584 * Sets the default "schema" setting for borrowed {@link Connection}s 585 * 586 * @param defaultSchema 587 * the default "schema" setting for borrowed {@link Connection}s 588 * @since 2.5.0 589 */ 590 public void setDefaultSchema(final String defaultSchema) { 591 this.defaultSchema = defaultSchema; 592 } 593 594 /** 595 * Sets the default "Transaction Isolation" setting for borrowed {@link Connection}s 596 * 597 * @param defaultTransactionIsolation 598 * the default "Transaction Isolation" setting for returned {@link Connection}s 599 */ 600 public void setDefaultTransactionIsolation(final int defaultTransactionIsolation) { 601 this.defaultTransactionIsolation = defaultTransactionIsolation; 602 } 603 604 /** 605 * @param disconnectionSqlCodes 606 * The disconnection SQL codes. 607 * @see #getDisconnectionSqlCodes() 608 * @since 2.1 609 */ 610 public void setDisconnectionSqlCodes(final Collection<String> disconnectionSqlCodes) { 611 this.disconnectionSqlCodes = disconnectionSqlCodes; 612 } 613 614 /** 615 * @param autoCommitOnReturn Whether to auto-commit on return. 616 * @deprecated Use {@link #setAutoCommitOnReturn(boolean)}. 617 */ 618 @Deprecated 619 public void setEnableAutoCommitOnReturn(final boolean autoCommitOnReturn) { 620 this.autoCommitOnReturn = autoCommitOnReturn; 621 } 622 623 /** 624 * @see #isFastFailValidation() 625 * @param fastFailValidation 626 * true means connections created by this factory will fast fail validation 627 * @since 2.1 628 */ 629 public void setFastFailValidation(final boolean fastFailValidation) { 630 this.fastFailValidation = fastFailValidation; 631 } 632 633 /** 634 * Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation, 635 * passivation and validation. A value of zero or less indicates an infinite lifetime. The default value is -1. 636 * 637 * @param maxConnDuration 638 * The maximum lifetime in milliseconds. 639 * @since 2.10.0 640 */ 641 public void setMaxConn(final Duration maxConnDuration) { 642 this.maxConnDuration = maxConnDuration; 643 } 644 645 /** 646 * Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation, 647 * passivation and validation. A value of zero or less indicates an infinite lifetime. The default value is -1. 648 * 649 * @param maxConnLifetimeMillis 650 * The maximum lifetime in milliseconds. 651 * @deprecated Use {@link #setMaxConn(Duration)}. 652 */ 653 @Deprecated 654 public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) { 655 this.maxConnDuration = Duration.ofMillis(maxConnLifetimeMillis); 656 } 657 658 /** 659 * Sets the maximum number of open prepared statements. 660 * 661 * @param maxOpenPreparedStatements 662 * The maximum number of open prepared statements. 663 */ 664 public void setMaxOpenPreparedStatements(final int maxOpenPreparedStatements) { 665 this.maxOpenPreparedStatements = maxOpenPreparedStatements; 666 } 667 668 /** 669 * Deprecated due to typo in method name. 670 * 671 * @param maxOpenPreparedStatements 672 * The maximum number of open prepared statements. 673 * @deprecated Use {@link #setMaxOpenPreparedStatements(int)}. 674 */ 675 @Deprecated // Due to typo in method name. 676 public void setMaxOpenPrepatedStatements(final int maxOpenPreparedStatements) { 677 setMaxOpenPreparedStatements(maxOpenPreparedStatements); 678 } 679 680 /** 681 * Sets the {@link ObjectPool} in which to pool {@link Connection}s. 682 * 683 * @param pool 684 * the {@link ObjectPool} in which to pool those {@link Connection}s 685 */ 686 public synchronized void setPool(final ObjectPool<PoolableConnection> pool) { 687 if (null != this.pool && pool != this.pool) { 688 Utils.closeQuietly(this.pool); 689 } 690 this.pool = pool; 691 } 692 693 public void setPoolStatements(final boolean poolStatements) { 694 this.poolStatements = poolStatements; 695 } 696 697 public void setRollbackOnReturn(final boolean rollbackOnReturn) { 698 this.rollbackOnReturn = rollbackOnReturn; 699 } 700 701 /** 702 * Sets the query I use to {@link #validateObject validate} {@link Connection}s. Should return at least one row. If 703 * not specified, {@link Connection#isValid(int)} will be used to validate connections. 704 * 705 * @param validationQuery 706 * a query to use to {@link #validateObject validate} {@link Connection}s. 707 */ 708 public void setValidationQuery(final String validationQuery) { 709 this.validationQuery = validationQuery; 710 } 711 712 /** 713 * Sets the validation query timeout, the amount of time, that connection validation will wait for a response from the 714 * database when executing a validation query. Use a value less than or equal to 0 for no timeout. 715 * 716 * @param validationQueryTimeoutDuration new validation query timeout duration. 717 * @since 2.10.0 718 */ 719 public void setValidationQueryTimeout(final Duration validationQueryTimeoutDuration) { 720 this.validationQueryTimeoutDuration = validationQueryTimeoutDuration; 721 } 722 723 /** 724 * Sets the validation query timeout, the amount of time, in seconds, that connection validation will wait for a 725 * response from the database when executing a validation query. Use a value less than or equal to 0 for no timeout. 726 * 727 * @param validationQueryTimeoutSeconds 728 * new validation query timeout value in seconds 729 * @deprecated {@link #setValidationQueryTimeout(Duration)}. 730 */ 731 @Deprecated 732 public void setValidationQueryTimeout(final int validationQueryTimeoutSeconds) { 733 this.validationQueryTimeoutDuration = Duration.ofSeconds(validationQueryTimeoutSeconds); 734 } 735 736 /** 737 * Validates the given connection if it is open. 738 * 739 * @param conn the connection to validate. 740 * @throws SQLException if the connection is closed or validate fails. 741 */ 742 public void validateConnection(final PoolableConnection conn) throws SQLException { 743 if (conn.isClosed()) { 744 throw new SQLException("validateConnection: connection closed"); 745 } 746 conn.validate(validationQuery, validationQueryTimeoutDuration); 747 } 748 749 private void validateLifetime(final PooledObject<PoolableConnection> p) throws LifetimeExceededException { 750 Utils.validateLifetime(p, maxConnDuration); 751 } 752 753 @Override 754 public boolean validateObject(final PooledObject<PoolableConnection> p) { 755 try { 756 validateLifetime(p); 757 validateConnection(p.getObject()); 758 return true; 759 } catch (final Exception e) { 760 if (log.isDebugEnabled()) { 761 log.debug(Utils.getMessage("poolableConnectionFactory.validateObject.fail"), e); 762 } 763 return false; 764 } 765 } 766}