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