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.util.Arrays; 023 024import org.apache.commons.dbcp2.PoolingConnection.StatementType; 025 026/** 027 * A key uniquely identifying {@link java.sql.PreparedStatement PreparedStatement}s. 028 * 029 * @since 2.0 030 */ 031public class PStmtKey { 032 033 /** 034 * Builder for prepareCall(String sql). 035 */ 036 private class PreparedCallSQL implements StatementBuilder { 037 @Override 038 public Statement createStatement(final Connection connection) throws SQLException { 039 return connection.prepareCall(sql); 040 } 041 } 042 043 /** 044 * Builder for prepareCall(String sql, int resultSetType, int resultSetConcurrency). 045 */ 046 private class PreparedCallWithResultSetConcurrency implements StatementBuilder { 047 @Override 048 public Statement createStatement(final Connection connection) throws SQLException { 049 return connection.prepareCall(sql, resultSetType.intValue(), resultSetConcurrency.intValue()); 050 } 051 } 052 053 /** 054 * Builder for prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability). 055 */ 056 private class PreparedCallWithResultSetHoldability implements StatementBuilder { 057 @Override 058 public Statement createStatement(final Connection connection) throws SQLException { 059 return connection.prepareCall(sql, resultSetType.intValue(), resultSetConcurrency.intValue(), 060 resultSetHoldability.intValue()); 061 } 062 } 063 064 /** 065 * Builder for prepareStatement(String sql). 066 */ 067 private class PreparedStatementSQL implements StatementBuilder { 068 @Override 069 public Statement createStatement(final Connection connection) throws SQLException { 070 return connection.prepareStatement(sql); 071 } 072 } 073 074 /** 075 * Builder for prepareStatement(String sql, int autoGeneratedKeys). 076 */ 077 private class PreparedStatementWithAutoGeneratedKeys implements StatementBuilder { 078 @Override 079 public Statement createStatement(final Connection connection) throws SQLException { 080 return connection.prepareStatement(sql, autoGeneratedKeys.intValue()); 081 } 082 } 083 084 /** 085 * Builder for prepareStatement(String sql, int[] columnIndexes). 086 */ 087 private class PreparedStatementWithColumnIndexes implements StatementBuilder { 088 @Override 089 public Statement createStatement(final Connection connection) throws SQLException { 090 return connection.prepareStatement(sql, columnIndexes); 091 } 092 } 093 094 /** 095 * Builder for prepareStatement(String sql, String[] columnNames). 096 */ 097 private class PreparedStatementWithColumnNames implements StatementBuilder { 098 @Override 099 public Statement createStatement(final Connection connection) throws SQLException { 100 return connection.prepareStatement(sql, columnNames); 101 } 102 } 103 104 /** 105 * Builder for prepareStatement(String sql, int resultSetType, int resultSetConcurrency). 106 */ 107 private class PreparedStatementWithResultSetConcurrency implements StatementBuilder { 108 @Override 109 public Statement createStatement(final Connection connection) throws SQLException { 110 return connection.prepareStatement(sql, resultSetType.intValue(), resultSetConcurrency.intValue()); 111 } 112 } 113 114 /** 115 * Builder for prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability). 116 */ 117 private class PreparedStatementWithResultSetHoldability implements StatementBuilder { 118 @Override 119 public Statement createStatement(final Connection connection) throws SQLException { 120 return connection.prepareStatement(sql, resultSetType.intValue(), resultSetConcurrency.intValue(), 121 resultSetHoldability.intValue()); 122 } 123 } 124 125 /** 126 * Interface for Prepared or Callable Statement. 127 */ 128 private interface StatementBuilder { 129 Statement createStatement(Connection connection) throws SQLException; 130 } 131 132 /** 133 * SQL defining Prepared or Callable Statement 134 */ 135 private final String sql; 136 137 /** 138 * Result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, 139 * or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. 140 */ 141 private final Integer resultSetType; 142 143 /** 144 * Result set concurrency. A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 145 * <code>ResultSet.CONCUR_UPDATABLE</code>. 146 */ 147 private final Integer resultSetConcurrency; 148 149 /** 150 * Result set holdability. One of the following <code>ResultSet</code> constants: 151 * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>. 152 */ 153 private final Integer resultSetHoldability; 154 155 /** Database catalog. */ 156 private final String catalog; 157 158 /** Database schema. */ 159 private final String schema; 160 161 /** 162 * A flag indicating whether auto-generated keys should be returned; one of 163 * <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>. 164 */ 165 private final Integer autoGeneratedKeys; 166 167 /** 168 * An array of column indexes indicating the columns that should be returned from the inserted row or rows. 169 */ 170 private final int[] columnIndexes; 171 172 /** 173 * An array of column names indicating the columns that should be returned from the inserted row or rows. 174 */ 175 private final String[] columnNames; 176 177 /** 178 * Statement type, prepared or callable. 179 */ 180 private final StatementType statementType; 181 182 /** Statement builder */ 183 private transient StatementBuilder builder; 184 185 /** 186 * Constructs a key to uniquely identify a prepared statement. 187 * 188 * @param sql 189 * The SQL statement. 190 * @deprecated Use {@link #PStmtKey(String, String, String)}. 191 */ 192 @Deprecated 193 public PStmtKey(final String sql) { 194 this(sql, null, StatementType.PREPARED_STATEMENT); 195 } 196 197 /** 198 * Constructs a key to uniquely identify a prepared statement. 199 * 200 * @param sql 201 * The SQL statement. 202 * @param resultSetType 203 * A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 204 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. 205 * @param resultSetConcurrency 206 * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 207 * <code>ResultSet.CONCUR_UPDATABLE</code>. 208 * @deprecated Use {@link #PStmtKey(String, String, String, int, int)}. 209 */ 210 @Deprecated 211 public PStmtKey(final String sql, final int resultSetType, final int resultSetConcurrency) { 212 this(sql, null, resultSetType, resultSetConcurrency, StatementType.PREPARED_STATEMENT); 213 } 214 215 /** 216 * Constructs a key to uniquely identify a prepared statement. 217 * 218 * @param sql 219 * The SQL statement. 220 * @param catalog 221 * The catalog. 222 * @deprecated Use {@link #PStmtKey(String, String, String)}. 223 */ 224 @Deprecated 225 public PStmtKey(final String sql, final String catalog) { 226 this(sql, catalog, StatementType.PREPARED_STATEMENT); 227 } 228 229 /** 230 * Constructs a key to uniquely identify a prepared statement. 231 * 232 * @param sql 233 * The SQL statement. 234 * @param catalog 235 * The catalog. 236 * @param autoGeneratedKeys 237 * A flag indicating whether auto-generated keys should be returned; one of 238 * <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>. 239 * @deprecated Use {@link #PStmtKey(String, String, String, int)}. 240 */ 241 @Deprecated 242 public PStmtKey(final String sql, final String catalog, final int autoGeneratedKeys) { 243 this(sql, catalog, StatementType.PREPARED_STATEMENT, Integer.valueOf(autoGeneratedKeys)); 244 } 245 246 /** 247 * Constructs a key to uniquely identify a prepared statement. 248 * 249 * @param sql 250 * The SQL statement. 251 * @param catalog 252 * The catalog. 253 * @param resultSetType 254 * A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 255 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. 256 * @param resultSetConcurrency 257 * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 258 * <code>ResultSet.CONCUR_UPDATABLE</code>. 259 * @deprecated Use @link {@link #PStmtKey(String, String, String, int, int)}. 260 */ 261 @Deprecated 262 public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency) { 263 this(sql, catalog, resultSetType, resultSetConcurrency, StatementType.PREPARED_STATEMENT); 264 } 265 266 /** 267 * Constructs a key to uniquely identify a prepared statement. 268 * 269 * @param sql 270 * The SQL statement. 271 * @param catalog 272 * The catalog. 273 * @param resultSetType 274 * a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 275 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. 276 * @param resultSetConcurrency 277 * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 278 * <code>ResultSet.CONCUR_UPDATABLE</code> 279 * @param resultSetHoldability 280 * One of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> 281 * or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>. 282 * @deprecated Use {@link #PStmtKey(String, String, String, int, int, int)}. 283 */ 284 @Deprecated 285 public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency, 286 final int resultSetHoldability) { 287 this(sql, catalog, resultSetType, resultSetConcurrency, resultSetHoldability, StatementType.PREPARED_STATEMENT); 288 } 289 290 /** 291 * Constructs a key to uniquely identify a prepared statement. 292 * 293 * @param sql 294 * The SQL statement. 295 * @param catalog 296 * The catalog. 297 * @param resultSetType 298 * a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 299 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code> 300 * @param resultSetConcurrency 301 * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 302 * <code>ResultSet.CONCUR_UPDATABLE</code>. 303 * @param resultSetHoldability 304 * One of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> 305 * or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>. 306 * @param statementType 307 * The SQL statement type, prepared or callable. 308 * @deprecated Use {@link #PStmtKey(String, String, String, int, int, int, PoolingConnection.StatementType)} 309 */ 310 @Deprecated 311 public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency, 312 final int resultSetHoldability, final StatementType statementType) { 313 this.sql = sql; 314 this.catalog = catalog; 315 this.schema = null; 316 this.resultSetType = Integer.valueOf(resultSetType); 317 this.resultSetConcurrency = Integer.valueOf(resultSetConcurrency); 318 this.resultSetHoldability = Integer.valueOf(resultSetHoldability); 319 this.statementType = statementType; 320 this.autoGeneratedKeys = null; 321 this.columnIndexes = null; 322 this.columnNames = null; 323 // create builder 324 if (statementType == StatementType.PREPARED_STATEMENT) { 325 this.builder = new PreparedStatementWithResultSetHoldability(); 326 } else if (statementType == StatementType.CALLABLE_STATEMENT) { 327 this.builder = new PreparedCallWithResultSetHoldability(); 328 } 329 } 330 331 /** 332 * Constructs a key to uniquely identify a prepared statement. 333 * 334 * @param sql 335 * The SQL statement. 336 * @param catalog 337 * The catalog. 338 * @param resultSetType 339 * A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 340 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. 341 * @param resultSetConcurrency 342 * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 343 * <code>ResultSet.CONCUR_UPDATABLE</code>. 344 * @param statementType 345 * The SQL statement type, prepared or callable. 346 * @deprecated Use {@link #PStmtKey(String, String, String, int, int, PoolingConnection.StatementType)}. 347 */ 348 @Deprecated 349 public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency, 350 final StatementType statementType) { 351 this.sql = sql; 352 this.catalog = catalog; 353 this.schema = null; 354 this.resultSetType = Integer.valueOf(resultSetType); 355 this.resultSetConcurrency = Integer.valueOf(resultSetConcurrency); 356 this.resultSetHoldability = null; 357 this.statementType = statementType; 358 this.autoGeneratedKeys = null; 359 this.columnIndexes = null; 360 this.columnNames = null; 361 // create builder 362 if (statementType == StatementType.PREPARED_STATEMENT) { 363 this.builder = new PreparedStatementWithResultSetConcurrency(); 364 } else if (statementType == StatementType.CALLABLE_STATEMENT) { 365 this.builder = new PreparedCallWithResultSetConcurrency(); 366 } 367 } 368 369 /** 370 * Constructs a key to uniquely identify a prepared statement. 371 * 372 * @param sql 373 * The SQL statement. 374 * @param catalog 375 * The catalog. 376 * @param columnIndexes 377 * An array of column indexes indicating the columns that should be returned from the inserted row or 378 * rows. 379 * @deprecated Use {@link #PStmtKey(String, String, String, int[])}. 380 */ 381 @Deprecated 382 public PStmtKey(final String sql, final String catalog, final int[] columnIndexes) { 383 this.sql = sql; 384 this.catalog = catalog; 385 this.schema = null; 386 this.statementType = StatementType.PREPARED_STATEMENT; 387 this.autoGeneratedKeys = null; 388 this.columnIndexes = columnIndexes == null ? null : Arrays.copyOf(columnIndexes, columnIndexes.length); 389 this.columnNames = null; 390 this.resultSetType = null; 391 this.resultSetConcurrency = null; 392 this.resultSetHoldability = null; 393 // create builder 394 this.builder = new PreparedStatementWithColumnIndexes(); 395 } 396 397 /** 398 * Constructs a key to uniquely identify a prepared statement. 399 * 400 * @param sql 401 * The SQL statement. 402 * @param catalog 403 * The catalog. 404 * @param statementType 405 * The SQL statement type, prepared or callable. 406 * @deprecated Use {@link #PStmtKey(String, String, String, PoolingConnection.StatementType)}. 407 */ 408 @Deprecated 409 public PStmtKey(final String sql, final String catalog, final StatementType statementType) { 410 this.sql = sql; 411 this.catalog = catalog; 412 this.schema = null; 413 this.statementType = statementType; 414 this.autoGeneratedKeys = null; 415 this.columnIndexes = null; 416 this.columnNames = null; 417 this.resultSetType = null; 418 this.resultSetConcurrency = null; 419 this.resultSetHoldability = null; 420 // create builder 421 if (statementType == StatementType.PREPARED_STATEMENT) { 422 this.builder = new PreparedStatementSQL(); 423 } else if (statementType == StatementType.CALLABLE_STATEMENT) { 424 this.builder = new PreparedCallSQL(); 425 } 426 } 427 428 /** 429 * Constructs a key to uniquely identify a prepared statement. 430 * 431 * @param sql 432 * The SQL statement. 433 * @param catalog 434 * The catalog. 435 * @param statementType 436 * The SQL statement type, prepared or callable. 437 * @param autoGeneratedKeys 438 * A flag indicating whether auto-generated keys should be returned; one of 439 * <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>. 440 * @deprecated Use {@link #PStmtKey(String, String, String, PoolingConnection.StatementType, Integer)} 441 */ 442 @Deprecated 443 public PStmtKey(final String sql, final String catalog, final StatementType statementType, 444 final Integer autoGeneratedKeys) { 445 this.sql = sql; 446 this.catalog = catalog; 447 this.schema = null; 448 this.statementType = statementType; 449 this.autoGeneratedKeys = autoGeneratedKeys; 450 this.columnIndexes = null; 451 this.columnNames = null; 452 this.resultSetType = null; 453 this.resultSetConcurrency = null; 454 this.resultSetHoldability = null; 455 // create builder 456 if (statementType == StatementType.PREPARED_STATEMENT) { 457 this.builder = new PreparedStatementWithAutoGeneratedKeys(); 458 } else if (statementType == StatementType.CALLABLE_STATEMENT) { 459 this.builder = new PreparedCallSQL(); 460 } 461 } 462 463 /** 464 * Constructs a key to uniquely identify a prepared statement. 465 * 466 * @param sql 467 * The SQL statement. 468 * @param catalog 469 * The catalog. 470 * @param schema 471 * The schema 472 * @since 2.5.0 473 */ 474 public PStmtKey(final String sql, final String catalog, final String schema) { 475 this(sql, catalog, schema, StatementType.PREPARED_STATEMENT); 476 } 477 478 /** 479 * Constructs a key to uniquely identify a prepared statement. 480 * 481 * @param sql 482 * The SQL statement. 483 * @param catalog 484 * The catalog. 485 * @param schema 486 * The schema 487 * @param autoGeneratedKeys 488 * A flag indicating whether auto-generated keys should be returned; one of 489 * <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>. 490 * @since 2.5.0 491 */ 492 public PStmtKey(final String sql, final String catalog, final String schema, final int autoGeneratedKeys) { 493 this(sql, catalog, schema, StatementType.PREPARED_STATEMENT, Integer.valueOf(autoGeneratedKeys)); 494 } 495 496 /** 497 * Constructs a key to uniquely identify a prepared statement. 498 * 499 * @param sql 500 * The SQL statement. 501 * @param catalog 502 * The catalog. 503 * @param schema 504 * The schema 505 * @param resultSetType 506 * A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 507 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. 508 * @param resultSetConcurrency 509 * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 510 * <code>ResultSet.CONCUR_UPDATABLE</code>. 511 */ 512 public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency) { 513 this(sql, catalog, schema, resultSetType, resultSetConcurrency, StatementType.PREPARED_STATEMENT); 514 } 515 516 /** 517 * Constructs a key to uniquely identify a prepared statement. 518 * 519 * @param sql 520 * The SQL statement. 521 * @param catalog 522 * The catalog. 523 * @param schema 524 * The schema 525 * @param resultSetType 526 * a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 527 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. 528 * @param resultSetConcurrency 529 * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 530 * <code>ResultSet.CONCUR_UPDATABLE</code> 531 * @param resultSetHoldability 532 * One of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> 533 * or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>. 534 * @since 2.5.0 535 */ 536 public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency, 537 final int resultSetHoldability) { 538 this(sql, catalog, schema, resultSetType, resultSetConcurrency, resultSetHoldability, StatementType.PREPARED_STATEMENT); 539 } 540 541 /** 542 * Constructs a key to uniquely identify a prepared statement. 543 * 544 * @param sql 545 * The SQL statement. 546 * @param catalog 547 * The catalog. 548 * @param schema 549 * The schema. 550 * @param resultSetType 551 * a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 552 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code> 553 * @param resultSetConcurrency 554 * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 555 * <code>ResultSet.CONCUR_UPDATABLE</code>. 556 * @param resultSetHoldability 557 * One of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> 558 * or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>. 559 * @param statementType 560 * The SQL statement type, prepared or callable. 561 * @since 2.5.0 562 */ 563 public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency, 564 final int resultSetHoldability, final StatementType statementType) { 565 this.sql = sql; 566 this.catalog = catalog; 567 this.schema = schema; 568 this.resultSetType = Integer.valueOf(resultSetType); 569 this.resultSetConcurrency = Integer.valueOf(resultSetConcurrency); 570 this.resultSetHoldability = Integer.valueOf(resultSetHoldability); 571 this.statementType = statementType; 572 this.autoGeneratedKeys = null; 573 this.columnIndexes = null; 574 this.columnNames = null; 575 // create builder 576 if (statementType == StatementType.PREPARED_STATEMENT) { 577 this.builder = new PreparedStatementWithResultSetHoldability(); 578 } else if (statementType == StatementType.CALLABLE_STATEMENT) { 579 this.builder = new PreparedCallWithResultSetHoldability(); 580 } 581 } 582 583 /** 584 * Constructs a key to uniquely identify a prepared statement. 585 * 586 * @param sql 587 * The SQL statement. 588 * @param catalog 589 * The catalog. 590 * @param schema 591 * The schema. 592 * @param resultSetType 593 * A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 594 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. 595 * @param resultSetConcurrency 596 * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 597 * <code>ResultSet.CONCUR_UPDATABLE</code>. 598 * @param statementType 599 * The SQL statement type, prepared or callable. 600 * @since 2.5.0 601 */ 602 public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency, 603 final StatementType statementType) { 604 this.sql = sql; 605 this.catalog = catalog; 606 this.schema = schema; 607 this.resultSetType = Integer.valueOf(resultSetType); 608 this.resultSetConcurrency = Integer.valueOf(resultSetConcurrency); 609 this.resultSetHoldability = null; 610 this.statementType = statementType; 611 this.autoGeneratedKeys = null; 612 this.columnIndexes = null; 613 this.columnNames = null; 614 // create builder 615 if (statementType == StatementType.PREPARED_STATEMENT) { 616 this.builder = new PreparedStatementWithResultSetConcurrency(); 617 } else if (statementType == StatementType.CALLABLE_STATEMENT) { 618 this.builder = new PreparedCallWithResultSetConcurrency(); 619 } 620 } 621 622 /** 623 * Constructs a key to uniquely identify a prepared statement. 624 * 625 * @param sql 626 * The SQL statement. 627 * @param catalog 628 * The catalog. 629 * @param schema 630 * The schema. 631 * @param columnIndexes 632 * An array of column indexes indicating the columns that should be returned from the inserted row or 633 * rows. 634 */ 635 public PStmtKey(final String sql, final String catalog, final String schema, final int[] columnIndexes) { 636 this.sql = sql; 637 this.catalog = catalog; 638 this.schema = schema; 639 this.statementType = StatementType.PREPARED_STATEMENT; 640 this.autoGeneratedKeys = null; 641 this.columnIndexes = columnIndexes == null ? null : Arrays.copyOf(columnIndexes, columnIndexes.length); 642 this.columnNames = null; 643 this.resultSetType = null; 644 this.resultSetConcurrency = null; 645 this.resultSetHoldability = null; 646 // create builder 647 this.builder = new PreparedStatementWithColumnIndexes(); 648 } 649 650 /** 651 * Constructs a key to uniquely identify a prepared statement. 652 * 653 * @param sql 654 * The SQL statement. 655 * @param catalog 656 * The catalog. 657 * @param schema 658 * The schema. 659 * @param statementType 660 * The SQL statement type, prepared or callable. 661 * @since 2.5.0 662 */ 663 public PStmtKey(final String sql, final String catalog, final String schema, final StatementType statementType) { 664 this.sql = sql; 665 this.catalog = catalog; 666 this.schema = schema; 667 this.statementType = statementType; 668 this.autoGeneratedKeys = null; 669 this.columnIndexes = null; 670 this.columnNames = null; 671 this.resultSetType = null; 672 this.resultSetConcurrency = null; 673 this.resultSetHoldability = null; 674 // create builder 675 if (statementType == StatementType.PREPARED_STATEMENT) { 676 this.builder = new PreparedStatementSQL(); 677 } else if (statementType == StatementType.CALLABLE_STATEMENT) { 678 this.builder = new PreparedCallSQL(); 679 } 680 } 681 682 /** 683 * Constructs a key to uniquely identify a prepared statement. 684 * 685 * @param sql 686 * The SQL statement. 687 * @param catalog 688 * The catalog. 689 * @param schema 690 * The schema. 691 * @param statementType 692 * The SQL statement type, prepared or callable. 693 * @param autoGeneratedKeys 694 * A flag indicating whether auto-generated keys should be returned; one of 695 * <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>. 696 * @since 2.5.0 697 */ 698 public PStmtKey(final String sql, final String catalog, final String schema, final StatementType statementType, 699 final Integer autoGeneratedKeys) { 700 this.sql = sql; 701 this.catalog = catalog; 702 this.schema = schema; 703 this.statementType = statementType; 704 this.autoGeneratedKeys = autoGeneratedKeys; 705 this.columnIndexes = null; 706 this.columnNames = null; 707 this.resultSetType = null; 708 this.resultSetConcurrency = null; 709 this.resultSetHoldability = null; 710 // create builder 711 if (statementType == StatementType.PREPARED_STATEMENT) { 712 this.builder = new PreparedStatementWithAutoGeneratedKeys(); 713 } else if (statementType == StatementType.CALLABLE_STATEMENT) { 714 this.builder = new PreparedCallSQL(); 715 } 716 } 717 718 /** 719 * Constructs a key to uniquely identify a prepared statement. 720 * 721 * @param sql 722 * The SQL statement. 723 * @param catalog 724 * The catalog. 725 * @param schema 726 * The schema. 727 * @param columnNames 728 * An array of column names indicating the columns that should be returned from the inserted row or rows. 729 * @since 2.5.0 730 */ 731 public PStmtKey(final String sql, final String catalog, final String schema, final String[] columnNames) { 732 this.sql = sql; 733 this.catalog = catalog; 734 this.schema = schema; 735 this.statementType = StatementType.PREPARED_STATEMENT; 736 this.autoGeneratedKeys = null; 737 this.columnIndexes = null; 738 this.columnNames = columnNames == null ? null : Arrays.copyOf(columnNames, columnNames.length); 739 this.resultSetType = null; 740 this.resultSetConcurrency = null; 741 this.resultSetHoldability = null; 742 // create builder 743 builder = new PreparedStatementWithColumnNames(); 744 } 745 746 /** 747 * Constructs a key to uniquely identify a prepared statement. 748 * 749 * @param sql 750 * The SQL statement. 751 * @param catalog 752 * The catalog. 753 * @param columnNames 754 * An array of column names indicating the columns that should be returned from the inserted row or rows. 755 * @deprecated Use {@link #PStmtKey(String, String, String, String[])}. 756 */ 757 @Deprecated 758 public PStmtKey(final String sql, final String catalog, final String[] columnNames) { 759 this.sql = sql; 760 this.catalog = catalog; 761 this.schema = null; 762 this.statementType = StatementType.PREPARED_STATEMENT; 763 this.autoGeneratedKeys = null; 764 this.columnIndexes = null; 765 this.columnNames = columnNames == null ? null : Arrays.copyOf(columnNames, columnNames.length); 766 this.resultSetType = null; 767 this.resultSetConcurrency = null; 768 this.resultSetHoldability = null; 769 // create builder 770 builder = new PreparedStatementWithColumnNames(); 771 } 772 773 /** 774 * Creates a new Statement from the given Connection. 775 * 776 * @param connection 777 * The Connection to use to create the statement. 778 * @return The statement. 779 * @throws SQLException 780 * Thrown when there is a problem creating the statement. 781 */ 782 public Statement createStatement(final Connection connection) throws SQLException { 783 if (builder == null) { 784 throw new IllegalStateException("Prepared statement key is invalid."); 785 } 786 return builder.createStatement(connection); 787 } 788 789 @Override 790 public boolean equals(final Object obj) { 791 if (this == obj) { 792 return true; 793 } 794 if (obj == null) { 795 return false; 796 } 797 if (getClass() != obj.getClass()) { 798 return false; 799 } 800 final PStmtKey other = (PStmtKey) obj; 801 if (autoGeneratedKeys == null) { 802 if (other.autoGeneratedKeys != null) { 803 return false; 804 } 805 } else if (!autoGeneratedKeys.equals(other.autoGeneratedKeys)) { 806 return false; 807 } 808 if (catalog == null) { 809 if (other.catalog != null) { 810 return false; 811 } 812 } else if (!catalog.equals(other.catalog)) { 813 return false; 814 } 815 if (!Arrays.equals(columnIndexes, other.columnIndexes)) { 816 return false; 817 } 818 if (!Arrays.equals(columnNames, other.columnNames)) { 819 return false; 820 } 821 if (resultSetConcurrency == null) { 822 if (other.resultSetConcurrency != null) { 823 return false; 824 } 825 } else if (!resultSetConcurrency.equals(other.resultSetConcurrency)) { 826 return false; 827 } 828 if (resultSetHoldability == null) { 829 if (other.resultSetHoldability != null) { 830 return false; 831 } 832 } else if (!resultSetHoldability.equals(other.resultSetHoldability)) { 833 return false; 834 } 835 if (resultSetType == null) { 836 if (other.resultSetType != null) { 837 return false; 838 } 839 } else if (!resultSetType.equals(other.resultSetType)) { 840 return false; 841 } 842 if (schema == null) { 843 if (other.schema != null) { 844 return false; 845 } 846 } else if (!schema.equals(other.schema)) { 847 return false; 848 } 849 if (sql == null) { 850 if (other.sql != null) { 851 return false; 852 } 853 } else if (!sql.equals(other.sql)) { 854 return false; 855 } 856 if (statementType != other.statementType) { 857 return false; 858 } 859 return true; 860 } 861 862 /** 863 * Gets a flag indicating whether auto-generated keys should be returned; one of 864 * <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>. 865 * 866 * @return a flag indicating whether auto-generated keys should be returned. 867 */ 868 public Integer getAutoGeneratedKeys() { 869 return autoGeneratedKeys; 870 } 871 872 /** 873 * The catalog. 874 * 875 * @return The catalog. 876 */ 877 public String getCatalog() { 878 return catalog; 879 } 880 881 /** 882 * Gets an array of column indexes indicating the columns that should be returned from the inserted row or rows. 883 * 884 * @return An array of column indexes. 885 */ 886 public int[] getColumnIndexes() { 887 return columnIndexes; 888 } 889 890 /** 891 * Gets an array of column names indicating the columns that should be returned from the inserted row or rows. 892 * 893 * @return An array of column names. 894 */ 895 public String[] getColumnNames() { 896 return columnNames; 897 } 898 899 /** 900 * Gets the result set concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 901 * <code>ResultSet.CONCUR_UPDATABLE</code>. 902 * 903 * @return The result set concurrency type. 904 */ 905 public Integer getResultSetConcurrency() { 906 return resultSetConcurrency; 907 } 908 909 /** 910 * Gets the result set holdability, one of the following <code>ResultSet</code> constants: 911 * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>. 912 * 913 * @return The result set holdability. 914 */ 915 public Integer getResultSetHoldability() { 916 return resultSetHoldability; 917 } 918 919 /** 920 * Gets the result set type, one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 921 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. 922 * 923 * @return the result set type. 924 */ 925 public Integer getResultSetType() { 926 return resultSetType; 927 } 928 929 /** 930 * The schema. 931 * 932 * @return The catalog. 933 */ 934 public String getSchema() { 935 return schema; 936 } 937 938 /** 939 * Gets the SQL statement. 940 * 941 * @return the SQL statement. 942 */ 943 public String getSql() { 944 return sql; 945 } 946 947 /** 948 * The SQL statement type. 949 * 950 * @return The SQL statement type. 951 */ 952 public StatementType getStmtType() { 953 return statementType; 954 } 955 956 @Override 957 public int hashCode() { 958 final int prime = 31; 959 int result = 1; 960 result = prime * result + ((autoGeneratedKeys == null) ? 0 : autoGeneratedKeys.hashCode()); 961 result = prime * result + ((catalog == null) ? 0 : catalog.hashCode()); 962 result = prime * result + Arrays.hashCode(columnIndexes); 963 result = prime * result + Arrays.hashCode(columnNames); 964 result = prime * result + ((resultSetConcurrency == null) ? 0 : resultSetConcurrency.hashCode()); 965 result = prime * result + ((resultSetHoldability == null) ? 0 : resultSetHoldability.hashCode()); 966 result = prime * result + ((resultSetType == null) ? 0 : resultSetType.hashCode()); 967 result = prime * result + ((schema == null) ? 0 : schema.hashCode()); 968 result = prime * result + ((sql == null) ? 0 : sql.hashCode()); 969 result = prime * result + ((statementType == null) ? 0 : statementType.hashCode()); 970 return result; 971 } 972 973 @Override 974 public String toString() { 975 final StringBuffer buf = new StringBuffer(); 976 buf.append("PStmtKey: sql="); 977 buf.append(sql); 978 buf.append(", catalog="); 979 buf.append(catalog); 980 buf.append(", schema="); 981 buf.append(schema); 982 buf.append(", resultSetType="); 983 buf.append(resultSetType); 984 buf.append(", resultSetConcurrency="); 985 buf.append(resultSetConcurrency); 986 buf.append(", resultSetHoldability="); 987 buf.append(resultSetHoldability); 988 buf.append(", autoGeneratedKeys="); 989 buf.append(autoGeneratedKeys); 990 buf.append(", columnIndexes="); 991 buf.append(Arrays.toString(columnIndexes)); 992 buf.append(", columnNames="); 993 buf.append(Arrays.toString(columnNames)); 994 buf.append(", statementType="); 995 buf.append(statementType); 996 return buf.toString(); 997 } 998}