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 Collection<String> disconnectionIgnoreSqlCodes; 068 069 private boolean fastFailValidation = true; 070 071 private volatile ObjectPool<PoolableConnection> pool; 072 073 private Boolean defaultReadOnly; 074 075 private Boolean defaultAutoCommit; 076 077 private boolean autoCommitOnReturn = true; 078 079 private boolean rollbackOnReturn = true; 080 081 private int defaultTransactionIsolation = UNKNOWN_TRANSACTION_ISOLATION; 082 083 private String defaultCatalog; 084 085 private String defaultSchema; 086 087 private boolean cacheState; 088 089 private boolean poolStatements; 090 091 private boolean clearStatementPoolOnReturn; 092 093 private int maxOpenPreparedStatements = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY; 094 095 private Duration maxConnDuration = Duration.ofMillis(-1); 096 097 private final AtomicLong connectionIndex = new AtomicLong(); 098 099 private Duration defaultQueryTimeoutDuration; 100 101 /** 102 * Creates a new {@code PoolableConnectionFactory}. 103 * 104 * @param connFactory 105 * the {@link ConnectionFactory} from which to obtain base {@link Connection}s 106 * @param dataSourceJmxObjectName 107 * The JMX object name, may be null. 108 */ 109 public PoolableConnectionFactory(final ConnectionFactory connFactory, final ObjectName dataSourceJmxObjectName) { 110 this.connectionFactory = connFactory; 111 this.dataSourceJmxObjectName = dataSourceJmxObjectName; 112 } 113 114 @Override 115 public void activateObject(final PooledObject<PoolableConnection> p) throws SQLException { 116 117 validateLifetime(p); 118 119 final PoolableConnection pConnection = p.getObject(); 120 pConnection.activate(); 121 122 if (defaultAutoCommit != null && pConnection.getAutoCommit() != defaultAutoCommit) { 123 pConnection.setAutoCommit(defaultAutoCommit); 124 } 125 if (defaultTransactionIsolation != UNKNOWN_TRANSACTION_ISOLATION 126 && pConnection.getTransactionIsolation() != defaultTransactionIsolation) { 127 pConnection.setTransactionIsolation(defaultTransactionIsolation); 128 } 129 if (defaultReadOnly != null && pConnection.isReadOnly() != defaultReadOnly) { 130 pConnection.setReadOnly(defaultReadOnly); 131 } 132 if (defaultCatalog != null && !defaultCatalog.equals(pConnection.getCatalog())) { 133 pConnection.setCatalog(defaultCatalog); 134 } 135 if (defaultSchema != null && !defaultSchema.equals(Jdbc41Bridge.getSchema(pConnection))) { 136 Jdbc41Bridge.setSchema(pConnection, defaultSchema); 137 } 138 pConnection.setDefaultQueryTimeout(defaultQueryTimeoutDuration); 139 } 140 141 @Override 142 public void destroyObject(final PooledObject<PoolableConnection> p) throws SQLException { 143 p.getObject().reallyClose(); 144 } 145 146 /** 147 * @since 2.9.0 148 */ 149 @Override 150 public void destroyObject(final PooledObject<PoolableConnection> p, final DestroyMode mode) throws SQLException { 151 if (mode == DestroyMode.ABANDONED) { 152 Jdbc41Bridge.abort(p.getObject().getInnermostDelegate(), Runnable::run); 153 } else { 154 p.getObject().reallyClose(); 155 } 156 } 157 158 /** 159 * Gets the cache state to propagate in {@link #makeObject()}. 160 * 161 * @return The cache state. 162 * @since 2.6.0. 163 */ 164 public boolean getCacheState() { 165 return cacheState; 166 } 167 168 /** 169 * Gets the connection factory. 170 * 171 * @return The connection factory. 172 * @since 2.6.0. 173 */ 174 public ConnectionFactory getConnectionFactory() { 175 return connectionFactory; 176 } 177 178 /** 179 * Gets how many connections were created in {@link #makeObject()}. 180 * 181 * @return the connection count. 182 */ 183 protected AtomicLong getConnectionIndex() { 184 return connectionIndex; 185 } 186 187 /** 188 * Gets the collection of initialization SQL statements. 189 * 190 * @return The collection of initialization SQL statements. 191 * @since 2.6.0 192 */ 193 public Collection<String> getConnectionInitSqls() { 194 return connectionInitSqls; 195 } 196 197 /** 198 * Gets data source JMX ObjectName. 199 * 200 * @return The data source JMX ObjectName. 201 * @since 2.6.0. 202 */ 203 public ObjectName getDataSourceJmxName() { 204 return dataSourceJmxObjectName; 205 } 206 207 /** 208 * Gets the data source JMX ObjectName. 209 * 210 * @return The data source JMX ObjectName. 211 * @since 2.6.0 212 */ 213 public ObjectName getDataSourceJmxObjectName() { 214 return dataSourceJmxObjectName; 215 } 216 217 /** 218 * Gets the Default auto-commit value. 219 * 220 * @return The default auto-commit value. 221 * @since 2.6.0 222 */ 223 public Boolean getDefaultAutoCommit() { 224 return defaultAutoCommit; 225 } 226 227 /** 228 * Gets the default catalog. 229 * 230 * @return The default catalog. 231 * @since 2.6.0 232 */ 233 public String getDefaultCatalog() { 234 return defaultCatalog; 235 } 236 237 /** 238 * Gets the default query timeout in seconds. 239 * 240 * @return The default query timeout in seconds. 241 * @deprecated Use {@link #getDefaultQueryTimeoutDuration()}. 242 */ 243 @Deprecated 244 public Integer getDefaultQueryTimeout() { 245 return getDefaultQueryTimeoutSeconds(); 246 } 247 248 /** 249 * Gets the default query timeout Duration. 250 * 251 * @return The default query timeout Duration. 252 * @since 2.10.0 253 */ 254 public Duration getDefaultQueryTimeoutDuration() { 255 return defaultQueryTimeoutDuration; 256 } 257 258 /** 259 * Gets the default query timeout in seconds. 260 * 261 * @return The default query timeout in seconds. 262 * @since 2.6.0 263 * @deprecated Use {@link #getDefaultQueryTimeoutDuration()}. 264 */ 265 @Deprecated 266 public Integer getDefaultQueryTimeoutSeconds() { 267 return defaultQueryTimeoutDuration == null ? null : (int) defaultQueryTimeoutDuration.getSeconds(); 268 } 269 270 /** 271 * Gets the default read-only-value. 272 * 273 * @return The default read-only-value. 274 * @since 2.6.0 275 */ 276 public Boolean getDefaultReadOnly() { 277 return defaultReadOnly; 278 } 279 280 /** 281 * Gets the default schema. 282 * 283 * @return The default schema. 284 * @since 2.6.0 285 */ 286 public String getDefaultSchema() { 287 return defaultSchema; 288 } 289 290 /** 291 * Gets the default transaction isolation. 292 * 293 * @return The default transaction isolation. 294 * @since 2.6.0 295 */ 296 public int getDefaultTransactionIsolation() { 297 return defaultTransactionIsolation; 298 } 299 300 /** 301 * Gets the collection of SQL State codes that are not considered fatal disconnection codes. 302 * <p> 303 * This method returns the collection of SQL State codes that have been set to be ignored when 304 * determining if a {@link SQLException} signals a disconnection. These codes are excluded from 305 * being treated as fatal even if they match the typical disconnection criteria. 306 * </p> 307 * 308 * @return a {@link Collection} of SQL State codes that should be ignored for disconnection checks. 309 * @since 2.13.0 310 */ 311 public Collection<String> getDisconnectionIgnoreSqlCodes() { 312 return disconnectionIgnoreSqlCodes; 313 } 314 315 /** 316 * Gets SQL State codes considered to signal fatal conditions. 317 * <p> 318 * Overrides the defaults in {@link Utils#getDisconnectionSqlCodes()} (plus anything starting with 319 * {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). If this property is non-null and {@link #isFastFailValidation()} is 320 * {@code true}, whenever connections created by this factory generate exceptions with SQL State codes in this list, 321 * they will be marked as "fatally disconnected" and subsequent validations will fail fast (no attempt at isValid or 322 * validation query). 323 * </p> 324 * <p> 325 * If {@link #isFastFailValidation()} is {@code false} setting this property has no effect. 326 * </p> 327 * 328 * @return SQL State codes overriding defaults 329 * @since 2.1 330 */ 331 public Collection<String> getDisconnectionSqlCodes() { 332 return disconnectionSqlCodes; 333 } 334 335 /** 336 * Gets the Maximum connection duration. 337 * 338 * @return Maximum connection duration. 339 * @since 2.10.0 340 */ 341 public Duration getMaxConnDuration() { 342 return maxConnDuration; 343 } 344 345 /** 346 * Gets the Maximum connection lifetime in milliseconds. 347 * 348 * @return Maximum connection lifetime in milliseconds. 349 * @since 2.6.0 350 */ 351 public long getMaxConnLifetimeMillis() { 352 return maxConnDuration.toMillis(); 353 } 354 355 /** 356 * Gets the maximum number of open prepared statements. 357 * 358 * @return The maximum number of open prepared statements. 359 */ 360 protected int getMaxOpenPreparedStatements() { 361 return maxOpenPreparedStatements; 362 } 363 364 /** 365 * Returns the {@link ObjectPool} in which {@link Connection}s are pooled. 366 * 367 * @return the connection pool 368 */ 369 public synchronized ObjectPool<PoolableConnection> getPool() { 370 return pool; 371 } 372 373 /** 374 * Tests whether to pool statements. 375 * 376 * @return Whether to pool statements. 377 * @since 2.6.0. 378 */ 379 public boolean getPoolStatements() { 380 return poolStatements; 381 } 382 383 /** 384 * Gets the validation query. 385 * 386 * @return Validation query. 387 * @since 2.6.0 388 */ 389 public String getValidationQuery() { 390 return validationQuery; 391 } 392 393 /** 394 * Gets the query timeout in seconds. 395 * 396 * @return Validation query timeout in seconds. 397 * @since 2.10.0 398 */ 399 public Duration getValidationQueryTimeoutDuration() { 400 return validationQueryTimeoutDuration; 401 } 402 403 /** 404 * Gets the query timeout in seconds. 405 * 406 * @return Validation query timeout in seconds. 407 * @since 2.6.0 408 * @deprecated Use {@link #getValidationQueryTimeoutDuration()}. 409 */ 410 @Deprecated 411 public int getValidationQueryTimeoutSeconds() { 412 return (int) validationQueryTimeoutDuration.getSeconds(); 413 } 414 415 /** 416 * Initializes the given connection with the collection of SQL statements set in {@link #setConnectionInitSql(Collection)}. 417 * 418 * @param conn the connection to initialize. 419 * @throws SQLException if a database access error occurs or this method is called on a closed connection. 420 * @see #setConnectionInitSql(Collection) 421 */ 422 protected void initializeConnection(final Connection conn) throws SQLException { 423 final Collection<String> sqls = connectionInitSqls; 424 if (conn.isClosed()) { 425 throw new SQLException("initializeConnection: connection closed"); 426 } 427 if (!Utils.isEmpty(sqls)) { 428 try (Statement statement = conn.createStatement()) { 429 for (final String sql : sqls) { 430 statement.execute(Objects.requireNonNull(sql, "null connectionInitSqls element")); 431 } 432 } 433 } 434 } 435 436 /** 437 * Tests whether to set auto-commit on {@link #passivateObject(PooledObject)}. 438 * 439 * @return Whether to set auto-commit on {@link #passivateObject(PooledObject)}. 440 * @since 2.6.0 441 */ 442 public boolean isAutoCommitOnReturn() { 443 return autoCommitOnReturn; 444 } 445 446 /** 447 * Tests whether to set auto-commit on {@link #passivateObject(PooledObject)}. 448 * 449 * @return Whether to set auto-commit on {@link #passivateObject(PooledObject)}. 450 * @deprecated Use {@link #isAutoCommitOnReturn()}. 451 */ 452 @Deprecated 453 public boolean isEnableAutoCommitOnReturn() { 454 return autoCommitOnReturn; 455 } 456 457 /** 458 * True means that validation will fail immediately for connections that have previously thrown SQLExceptions with 459 * SQL State indicating fatal disconnection errors. 460 * 461 * @return true if connections created by this factory will fast fail validation. 462 * @see #setDisconnectionSqlCodes(Collection) 463 * @since 2.1 464 * @since 2.5.0 Defaults to true, previous versions defaulted to false. 465 */ 466 public boolean isFastFailValidation() { 467 return fastFailValidation; 468 } 469 470 /** 471 * Tests whether to rollback on return. 472 * 473 * @return Whether to rollback on return. 474 */ 475 public boolean isRollbackOnReturn() { 476 return rollbackOnReturn; 477 } 478 479 @Override 480 public PooledObject<PoolableConnection> makeObject() throws SQLException { 481 Connection conn = connectionFactory.createConnection(); 482 if (conn == null) { 483 throw new IllegalStateException("Connection factory returned null from createConnection"); 484 } 485 try { 486 initializeConnection(conn); 487 } catch (final SQLException e) { 488 // Make sure the connection is closed 489 Utils.closeQuietly((AutoCloseable) conn); 490 // Rethrow original exception so it is visible to caller 491 throw e; 492 } 493 494 final long connIndex = connectionIndex.getAndIncrement(); 495 496 if (poolStatements) { 497 conn = new PoolingConnection(conn); 498 final GenericKeyedObjectPoolConfig<DelegatingPreparedStatement> config = new GenericKeyedObjectPoolConfig<>(); 499 config.setMaxTotalPerKey(-1); 500 config.setBlockWhenExhausted(false); 501 config.setMaxWait(Duration.ZERO); 502 config.setMaxIdlePerKey(1); 503 config.setMaxTotal(maxOpenPreparedStatements); 504 if (dataSourceJmxObjectName != null) { 505 final StringBuilder base = new StringBuilder(dataSourceJmxObjectName.toString()); 506 base.append(Constants.JMX_CONNECTION_BASE_EXT); 507 base.append(connIndex); 508 config.setJmxNameBase(base.toString()); 509 config.setJmxNamePrefix(Constants.JMX_STATEMENT_POOL_PREFIX); 510 } else { 511 config.setJmxEnabled(false); 512 } 513 final PoolingConnection poolingConn = (PoolingConnection) conn; 514 final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> stmtPool = new GenericKeyedObjectPool<>(poolingConn, config); 515 poolingConn.setStatementPool(stmtPool); 516 poolingConn.setClearStatementPoolOnReturn(clearStatementPoolOnReturn); 517 poolingConn.setCacheState(cacheState); 518 } 519 520 // Register this connection with JMX 521 final ObjectName connJmxName; 522 if (dataSourceJmxObjectName == null) { 523 connJmxName = null; 524 } else { 525 final String name = dataSourceJmxObjectName.toString() + Constants.JMX_CONNECTION_BASE_EXT + connIndex; 526 try { 527 connJmxName = new ObjectName(name); 528 } catch (final MalformedObjectNameException e) { 529 Utils.closeQuietly((AutoCloseable) conn); 530 throw new SQLException(name, e); 531 } 532 } 533 534 final PoolableConnection pc = new PoolableConnection(conn, pool, connJmxName, 535 disconnectionSqlCodes, disconnectionIgnoreSqlCodes, fastFailValidation); 536 pc.setCacheState(cacheState); 537 538 return new DefaultPooledObject<>(pc); 539 } 540 541 @Override 542 public void passivateObject(final PooledObject<PoolableConnection> p) throws SQLException { 543 544 validateLifetime(p); 545 546 final PoolableConnection conn = p.getObject(); 547 Boolean connAutoCommit = null; 548 if (rollbackOnReturn) { 549 connAutoCommit = conn.getAutoCommit(); 550 if (!connAutoCommit && !conn.isReadOnly()) { 551 conn.rollback(); 552 } 553 } 554 555 conn.clearWarnings(); 556 557 // DBCP-97 / DBCP-399 / DBCP-351 Idle connections in the pool should 558 // have autoCommit enabled 559 if (autoCommitOnReturn) { 560 if (connAutoCommit == null) { 561 connAutoCommit = conn.getAutoCommit(); 562 } 563 if (!connAutoCommit) { 564 conn.setAutoCommit(true); 565 } 566 } 567 568 conn.passivate(); 569 } 570 571 /** 572 * Sets whether to set auto-commit on {@link #passivateObject(PooledObject)}. 573 * 574 * @param autoCommitOnReturn whether to set auto-commit. 575 */ 576 public void setAutoCommitOnReturn(final boolean autoCommitOnReturn) { 577 this.autoCommitOnReturn = autoCommitOnReturn; 578 } 579 580 /** 581 * Sets the cache state to propagate in {@link #makeObject()}. 582 * 583 * @param cacheState the cache state to propagate. 584 */ 585 public void setCacheState(final boolean cacheState) { 586 this.cacheState = cacheState; 587 } 588 589 /** 590 * Sets whether the pool of statements (which was enabled with {@link #setPoolStatements(boolean)}) should 591 * be cleared when the connection is returned to its pool. Default is false. 592 * 593 * @param clearStatementPoolOnReturn clear or not 594 * @since 2.8.0 595 */ 596 public void setClearStatementPoolOnReturn(final boolean clearStatementPoolOnReturn) { 597 this.clearStatementPoolOnReturn = clearStatementPoolOnReturn; 598 } 599 600 /** 601 * Sets the SQL statements I use to initialize newly created {@link Connection}s. Using {@code null} turns off 602 * connection initialization. 603 * 604 * @param connectionInitSqls 605 * SQL statement to initialize {@link Connection}s. 606 */ 607 public void setConnectionInitSql(final Collection<String> connectionInitSqls) { 608 this.connectionInitSqls = connectionInitSqls; 609 } 610 /** 611 * Sets the default "auto commit" setting for borrowed {@link Connection}s 612 * 613 * @param defaultAutoCommit 614 * the default "auto commit" setting for borrowed {@link Connection}s 615 */ 616 public void setDefaultAutoCommit(final Boolean defaultAutoCommit) { 617 this.defaultAutoCommit = defaultAutoCommit; 618 } 619 620 /** 621 * Sets the default "catalog" setting for borrowed {@link Connection}s 622 * 623 * @param defaultCatalog 624 * the default "catalog" setting for borrowed {@link Connection}s 625 */ 626 public void setDefaultCatalog(final String defaultCatalog) { 627 this.defaultCatalog = defaultCatalog; 628 } 629 630 /** 631 * Sets the query timeout Duration. 632 * 633 * @param defaultQueryTimeoutDuration the query timeout Duration. 634 * @since 2.10.0 635 */ 636 public void setDefaultQueryTimeout(final Duration defaultQueryTimeoutDuration) { 637 this.defaultQueryTimeoutDuration = defaultQueryTimeoutDuration; 638 } 639 640 /** 641 * Sets the query timeout in seconds. 642 * 643 * @param defaultQueryTimeoutSeconds the query timeout in seconds. 644 * @deprecated Use {@link #setDefaultQueryTimeout(Duration)}. 645 */ 646 @Deprecated 647 public void setDefaultQueryTimeout(final Integer defaultQueryTimeoutSeconds) { 648 this.defaultQueryTimeoutDuration = defaultQueryTimeoutSeconds == null ? null : Duration.ofSeconds(defaultQueryTimeoutSeconds); 649 } 650 651 /** 652 * Sets the default "read only" setting for borrowed {@link Connection}s 653 * 654 * @param defaultReadOnly 655 * the default "read only" setting for borrowed {@link Connection}s 656 */ 657 public void setDefaultReadOnly(final Boolean defaultReadOnly) { 658 this.defaultReadOnly = defaultReadOnly; 659 } 660 661 /** 662 * Sets the default "schema" setting for borrowed {@link Connection}s 663 * 664 * @param defaultSchema 665 * the default "schema" setting for borrowed {@link Connection}s 666 * @since 2.5.0 667 */ 668 public void setDefaultSchema(final String defaultSchema) { 669 this.defaultSchema = defaultSchema; 670 } 671 672 /** 673 * Sets the default "Transaction Isolation" setting for borrowed {@link Connection}s 674 * 675 * @param defaultTransactionIsolation 676 * the default "Transaction Isolation" setting for returned {@link Connection}s 677 */ 678 public void setDefaultTransactionIsolation(final int defaultTransactionIsolation) { 679 this.defaultTransactionIsolation = defaultTransactionIsolation; 680 } 681 682 /** 683 * Sets the disconnection SQL codes to ignore. 684 * 685 * @param disconnectionIgnoreSqlCodes 686 * The collection of SQL State codes to be ignored. 687 * @see #getDisconnectionIgnoreSqlCodes() 688 * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionSqlCodes}. 689 * @since 2.13.0 690 */ 691 public void setDisconnectionIgnoreSqlCodes(final Collection<String> disconnectionIgnoreSqlCodes) { 692 Utils.checkSqlCodes(disconnectionIgnoreSqlCodes, this.disconnectionSqlCodes); 693 this.disconnectionIgnoreSqlCodes = disconnectionIgnoreSqlCodes; 694 } 695 696 /** 697 * Sets the disconnection SQL codes. 698 * 699 * @param disconnectionSqlCodes 700 * The disconnection SQL codes. 701 * @see #getDisconnectionSqlCodes() 702 * @since 2.1 703 * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionIgnoreSqlCodes}. 704 */ 705 public void setDisconnectionSqlCodes(final Collection<String> disconnectionSqlCodes) { 706 Utils.checkSqlCodes(disconnectionSqlCodes, this.disconnectionIgnoreSqlCodes); 707 this.disconnectionSqlCodes = disconnectionSqlCodes; 708 } 709 710 /** 711 * Sets whether to set auto-commit on {@link #passivateObject(PooledObject)}. 712 * 713 * @param autoCommitOnReturn whether to set auto-commit. 714 */ 715 @Deprecated 716 public void setEnableAutoCommitOnReturn(final boolean autoCommitOnReturn) { 717 this.autoCommitOnReturn = autoCommitOnReturn; 718 } 719 720 /** 721 * @see #isFastFailValidation() 722 * @param fastFailValidation 723 * true means connections created by this factory will fast fail validation 724 * @since 2.1 725 */ 726 public void setFastFailValidation(final boolean fastFailValidation) { 727 this.fastFailValidation = fastFailValidation; 728 } 729 730 /** 731 * Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation, 732 * passivation and validation. A value of zero or less indicates an infinite lifetime. The default value is -1. 733 * 734 * @param maxConnDuration 735 * The maximum lifetime in milliseconds. 736 * @since 2.10.0 737 */ 738 public void setMaxConn(final Duration maxConnDuration) { 739 this.maxConnDuration = maxConnDuration; 740 } 741 742 /** 743 * Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation, 744 * passivation and validation. A value of zero or less indicates an infinite lifetime. The default value is -1. 745 * 746 * @param maxConnLifetimeMillis 747 * The maximum lifetime in milliseconds. 748 * @deprecated Use {@link #setMaxConn(Duration)}. 749 */ 750 @Deprecated 751 public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) { 752 this.maxConnDuration = Duration.ofMillis(maxConnLifetimeMillis); 753 } 754 755 /** 756 * Sets the maximum number of open prepared statements. 757 * 758 * @param maxOpenPreparedStatements 759 * The maximum number of open prepared statements. 760 */ 761 public void setMaxOpenPreparedStatements(final int maxOpenPreparedStatements) { 762 this.maxOpenPreparedStatements = maxOpenPreparedStatements; 763 } 764 765 /** 766 * Deprecated due to typo in method name. 767 * 768 * @param maxOpenPreparedStatements 769 * The maximum number of open prepared statements. 770 * @deprecated Use {@link #setMaxOpenPreparedStatements(int)}. 771 */ 772 @Deprecated // Due to typo in method name. 773 public void setMaxOpenPrepatedStatements(final int maxOpenPreparedStatements) { 774 setMaxOpenPreparedStatements(maxOpenPreparedStatements); 775 } 776 777 /** 778 * Sets the {@link ObjectPool} in which to pool {@link Connection}s. 779 * 780 * @param pool 781 * the {@link ObjectPool} in which to pool those {@link Connection}s 782 */ 783 public synchronized void setPool(final ObjectPool<PoolableConnection> pool) { 784 if (null != this.pool && pool != this.pool) { 785 Utils.closeQuietly(this.pool); 786 } 787 this.pool = pool; 788 } 789 790 /** 791 * Sets whether to pool statements. 792 * 793 * @param poolStatements whether to pool statements. 794 */ 795 public void setPoolStatements(final boolean poolStatements) { 796 this.poolStatements = poolStatements; 797 } 798 799 /** 800 * Sets whether to rollback on return. 801 * 802 * @param rollbackOnReturn whether to rollback on return. 803 */ 804 public void setRollbackOnReturn(final boolean rollbackOnReturn) { 805 this.rollbackOnReturn = rollbackOnReturn; 806 } 807 808 /** 809 * Sets the query I use to {@link #validateObject validate} {@link Connection}s. Should return at least one row. If 810 * not specified, {@link Connection#isValid(int)} will be used to validate connections. 811 * 812 * @param validationQuery 813 * a query to use to {@link #validateObject validate} {@link Connection}s. 814 */ 815 public void setValidationQuery(final String validationQuery) { 816 this.validationQuery = validationQuery; 817 } 818 819 /** 820 * Sets the validation query timeout, the amount of time, that connection validation will wait for a response from the 821 * database when executing a validation query. Use a value less than or equal to 0 for no timeout. 822 * 823 * @param validationQueryTimeoutDuration new validation query timeout duration. 824 * @since 2.10.0 825 */ 826 public void setValidationQueryTimeout(final Duration validationQueryTimeoutDuration) { 827 this.validationQueryTimeoutDuration = validationQueryTimeoutDuration; 828 } 829 830 /** 831 * Sets the validation query timeout, the amount of time, in seconds, that connection validation will wait for a 832 * response from the database when executing a validation query. Use a value less than or equal to 0 for no timeout. 833 * 834 * @param validationQueryTimeoutSeconds 835 * new validation query timeout value in seconds 836 * @deprecated {@link #setValidationQueryTimeout(Duration)}. 837 */ 838 @Deprecated 839 public void setValidationQueryTimeout(final int validationQueryTimeoutSeconds) { 840 this.validationQueryTimeoutDuration = Duration.ofSeconds(validationQueryTimeoutSeconds); 841 } 842 843 /** 844 * Validates the given connection if it is open. 845 * 846 * @param conn the connection to validate. 847 * @throws SQLException if the connection is closed or validate fails. 848 */ 849 public void validateConnection(final PoolableConnection conn) throws SQLException { 850 if (conn.isClosed()) { 851 throw new SQLException("validateConnection: connection closed"); 852 } 853 conn.validate(validationQuery, validationQueryTimeoutDuration); 854 } 855 856 private void validateLifetime(final PooledObject<PoolableConnection> p) throws LifetimeExceededException { 857 Utils.validateLifetime(p, maxConnDuration); 858 } 859 860 @Override 861 public boolean validateObject(final PooledObject<PoolableConnection> p) { 862 try { 863 validateLifetime(p); 864 validateConnection(p.getObject()); 865 return true; 866 } catch (final Exception e) { 867 if (log.isDebugEnabled()) { 868 log.debug(Utils.getMessage("poolableConnectionFactory.validateObject.fail"), e); 869 } 870 return false; 871 } 872 } 873}