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