1 package org.apache.ojb.broker.accesslayer; 2 3 17 18 import java.sql.CallableStatement ; 19 import java.sql.PreparedStatement ; 20 import java.sql.ResultSet ; 21 import java.sql.SQLException ; 22 import java.sql.Statement ; 23 import java.sql.Types ; 24 import java.util.Collection ; 25 import java.util.Enumeration ; 26 import java.util.Iterator ; 27 28 import org.apache.ojb.broker.Identity; 29 import org.apache.ojb.broker.PersistenceBroker; 30 import org.apache.ojb.broker.PersistenceBrokerException; 31 import org.apache.ojb.broker.PersistenceBrokerSQLException; 32 import org.apache.ojb.broker.core.ValueContainer; 33 import org.apache.ojb.broker.metadata.ArgumentDescriptor; 34 import org.apache.ojb.broker.metadata.ClassDescriptor; 35 import org.apache.ojb.broker.metadata.FieldDescriptor; 36 import org.apache.ojb.broker.metadata.ProcedureDescriptor; 37 import org.apache.ojb.broker.platforms.Platform; 38 import org.apache.ojb.broker.platforms.PlatformException; 39 import org.apache.ojb.broker.platforms.PlatformFactory; 40 import org.apache.ojb.broker.query.BetweenCriteria; 41 import org.apache.ojb.broker.query.Criteria; 42 import org.apache.ojb.broker.query.ExistsCriteria; 43 import org.apache.ojb.broker.query.FieldCriteria; 44 import org.apache.ojb.broker.query.InCriteria; 45 import org.apache.ojb.broker.query.NullCriteria; 46 import org.apache.ojb.broker.query.Query; 47 import org.apache.ojb.broker.query.SelectionCriteria; 48 import org.apache.ojb.broker.query.SqlCriteria; 49 import org.apache.ojb.broker.util.logging.Logger; 50 import org.apache.ojb.broker.util.logging.LoggerFactory; 51 52 59 public class StatementManager implements StatementManagerIF 60 { 61 private Logger m_log = LoggerFactory.getLogger(StatementManager.class); 62 63 64 private final PersistenceBroker m_broker; 65 private Platform m_platform; 66 75 private boolean m_eagerRelease; 76 private ConnectionManagerIF m_conMan; 77 78 public StatementManager(final PersistenceBroker pBroker) 79 { 80 this.m_broker = pBroker; 81 this.m_conMan = m_broker.serviceConnectionManager(); 82 m_eagerRelease = m_conMan.getConnectionDescriptor().getEagerRelease(); 83 m_platform = PlatformFactory.getPlatformFor(m_conMan.getConnectionDescriptor()); 84 } 85 86 public void closeResources(Statement stmt, ResultSet rs) 87 { 88 if (m_log.isDebugEnabled()) 89 m_log.debug("closeResources was called"); 90 try 91 { 92 m_platform.beforeStatementClose(stmt, rs); 93 if (stmt != null) 95 { 96 stmt.close(); 98 99 104 if (m_eagerRelease) 105 { 106 m_conMan.releaseConnection(); 107 } 108 109 } 110 m_platform.afterStatementClose(stmt, rs); 111 } 112 catch (PlatformException e) 113 { 114 m_log.error("Platform dependent operation failed", e); 115 } 116 catch (SQLException ignored) 117 { 118 if (m_log.isDebugEnabled()) 119 m_log.debug("Statement closing failed", ignored); 120 } 121 } 122 123 126 public void bindDelete(PreparedStatement stmt, Identity oid, ClassDescriptor cld) throws SQLException 127 { 128 Object [] pkValues = oid.getPrimaryKeyValues(); 129 FieldDescriptor[] pkFields = cld.getPkFields(); 130 int i = 0; 131 try 132 { 133 for (; i < pkValues.length; i++) 134 { 135 setObjectForStatement(stmt, i + 1, pkValues[i], pkFields[i].getJdbcType().getType()); 136 } 137 } 138 catch (SQLException e) 139 { 140 m_log.error("bindDelete failed for: " + oid.toString() + ", while set value '" + 141 pkValues[i] + "' for column " + pkFields[i].getColumnName()); 142 throw e; 143 } 144 } 145 146 149 public void bindDelete(PreparedStatement stmt, ClassDescriptor cld, Object obj) throws SQLException 150 { 151 if (cld.getDeleteProcedure() != null) 152 { 153 this.bindProcedure(stmt, cld, obj, cld.getDeleteProcedure()); 154 } 155 else 156 { 157 int index = 1; 158 ValueContainer[] values, currentLockingValues; 159 160 currentLockingValues = cld.getCurrentLockingValues(obj); 161 values = getKeyValues(m_broker, cld, obj); 163 for (int i = 0; i < values.length; i++) 164 { 165 setObjectForStatement(stmt, index, values[i].getValue(), values[i].getJdbcType().getType()); 166 index++; 167 } 168 169 values = currentLockingValues; 171 for (int i = 0; i < values.length; i++) 172 { 173 setObjectForStatement(stmt, index, values[i].getValue(), values[i].getJdbcType().getType()); 174 index++; 175 } 176 } 177 } 178 179 189 private int bindStatementValue(PreparedStatement stmt, int index, Object attributeOrQuery, Object value, ClassDescriptor cld) 190 throws SQLException 191 { 192 FieldDescriptor fld = null; 193 if (value instanceof Query) 195 { 196 Query subQuery = (Query) value; 197 return bindStatement(stmt, subQuery, cld.getRepository().getDescriptorFor(subQuery.getSearchClass()), index); 198 } 199 200 if (attributeOrQuery instanceof Query) 202 { 203 Query subQuery = (Query) attributeOrQuery; 204 bindStatement(stmt, subQuery, cld.getRepository().getDescriptorFor(subQuery.getSearchClass()), index); 205 } 206 else 207 { 208 fld = cld.getFieldDescriptorForPath((String ) attributeOrQuery); 209 } 210 211 if (fld != null) 212 { 213 if (value != null) 215 { 216 m_platform.setObjectForStatement(stmt, index, fld.getFieldConversion().javaToSql(value), fld.getJdbcType().getType()); 217 } 218 else 219 { 220 m_platform.setNullForStatement(stmt, index, fld.getJdbcType().getType()); 221 } 222 } 223 else 224 { 225 if (value != null) 226 { 227 stmt.setObject(index, value); 228 } 229 else 230 { 231 stmt.setNull(index, Types.NULL); 232 } 233 } 234 235 return ++index; } 237 238 246 private int bindStatement(PreparedStatement stmt, int index, SelectionCriteria crit, ClassDescriptor cld) throws SQLException 247 { 248 return bindStatementValue(stmt, index, crit.getAttribute(), crit.getValue(), cld); 249 } 250 251 258 private int bindStatement(PreparedStatement stmt, int index, NullCriteria crit) 259 { 260 return index; 261 } 262 263 270 private int bindStatement(PreparedStatement stmt, int index, FieldCriteria crit) 271 { 272 return index; 273 } 274 275 282 private int bindStatement(PreparedStatement stmt, int index, SqlCriteria crit) 283 { 284 return index; 285 } 286 287 295 private int bindStatement(PreparedStatement stmt, int index, BetweenCriteria crit, ClassDescriptor cld) throws SQLException 296 { 297 index = bindStatementValue(stmt, index, crit.getAttribute(), crit.getValue(), cld); 298 299 return bindStatementValue(stmt, index, crit.getAttribute(), crit.getValue2(), cld); 300 } 301 302 310 private int bindStatement(PreparedStatement stmt, int index, InCriteria crit, ClassDescriptor cld) throws SQLException 311 { 312 if (crit.getValue() instanceof Collection ) 313 { 314 Collection values = (Collection ) crit.getValue(); 315 Iterator iter = values.iterator(); 316 317 while (iter.hasNext()) 318 { 319 index = bindStatementValue(stmt, index, crit.getAttribute(), iter.next(), cld); 320 } 321 } 322 else 323 { 324 index = bindStatementValue(stmt, index, crit.getAttribute(), crit.getValue(), cld); 325 } 326 return index; 327 } 328 329 337 private int bindStatement(PreparedStatement stmt, int index, ExistsCriteria crit, ClassDescriptor cld) throws SQLException 338 { 339 Query subQuery = (Query) crit.getValue(); 340 341 if (subQuery.getCriteria() != null && !subQuery.getCriteria().isEmpty()) 343 { 344 return bindStatement(stmt, subQuery.getCriteria(), cld.getRepository().getDescriptorFor(subQuery.getSearchClass()), index); 345 346 } 348 else 349 { 350 return index; 351 } 352 } 353 354 357 public int bindStatement(PreparedStatement stmt, Query query, ClassDescriptor cld, int param) throws SQLException 358 { 359 int result; 360 361 result = bindStatement(stmt, query.getCriteria(), cld, param); 362 result = bindStatement(stmt, query.getHavingCriteria(), cld, result); 363 364 return result; 365 } 366 367 370 protected int bindStatement(PreparedStatement stmt, Criteria crit, ClassDescriptor cld, int param) throws SQLException 371 { 372 if (crit != null) 373 { 374 Enumeration e = crit.getElements(); 375 376 while (e.hasMoreElements()) 377 { 378 Object o = e.nextElement(); 379 if (o instanceof Criteria) 380 { 381 Criteria pc = (Criteria) o; 382 param = bindStatement(stmt, pc, cld, param); 383 } 384 else 385 { 386 SelectionCriteria c = (SelectionCriteria) o; 387 param = bindSelectionCriteria(stmt, param, c, cld); 389 390 for (int i = 0; i < c.getNumberOfExtentsToBind(); i++) 392 { 393 param = bindSelectionCriteria(stmt, param, c, cld); 394 } 395 } 396 } 397 } 398 return param; 399 } 400 401 409 private int bindSelectionCriteria(PreparedStatement stmt, int index, SelectionCriteria crit, ClassDescriptor cld) throws SQLException 410 { 411 if (crit instanceof NullCriteria) 412 index = bindStatement(stmt, index, (NullCriteria) crit); 413 else if (crit instanceof BetweenCriteria) 414 index = bindStatement(stmt, index, (BetweenCriteria) crit, cld); 415 else if (crit instanceof InCriteria) 416 index = bindStatement(stmt, index, (InCriteria) crit, cld); 417 else if (crit instanceof SqlCriteria) 418 index = bindStatement(stmt, index, (SqlCriteria) crit); 419 else if (crit instanceof FieldCriteria) 420 index = bindStatement(stmt, index, (FieldCriteria) crit); 421 else if (crit instanceof ExistsCriteria) 422 index = bindStatement(stmt, index, (ExistsCriteria) crit, cld); 423 else 424 index = bindStatement(stmt, index, crit, cld); 425 426 return index; 427 } 428 429 432 public void bindInsert(PreparedStatement stmt, ClassDescriptor cld, Object obj) throws java.sql.SQLException 433 { 434 ValueContainer[] values; 435 cld.updateLockingValues(obj); 437 if (cld.getInsertProcedure() != null) 438 { 439 this.bindProcedure(stmt, cld, obj, cld.getInsertProcedure()); 440 } 441 else 442 { 443 values = getAllValues(cld, obj); 444 for (int i = 0; i < values.length; i++) 445 { 446 setObjectForStatement(stmt, i + 1, values[i].getValue(), values[i].getJdbcType().getType()); 447 } 448 } 449 } 450 451 454 public void bindSelect(PreparedStatement stmt, Identity oid, ClassDescriptor cld, boolean callableStmt) throws SQLException 455 { 456 ValueContainer[] values = null; 457 int i = 0; 458 int j = 0; 459 460 if (cld == null) 461 { 462 cld = m_broker.getClassDescriptor(oid.getObjectsRealClass()); 463 } 464 try 465 { 466 if(callableStmt) 467 { 468 m_platform.registerOutResultSet((CallableStatement ) stmt, 1); 470 j++; 471 } 472 473 values = getKeyValues(m_broker, cld, oid); 474 for (; i < values.length; i++, j++) 475 { 476 setObjectForStatement(stmt, j + 1, values[i].getValue(), values[i].getJdbcType().getType()); 477 } 478 } 479 catch (SQLException e) 480 { 481 m_log.error("bindSelect failed for: " + oid.toString() + ", PK: " + i + ", value: " + values[i]); 482 throw e; 483 } 484 } 485 486 489 public void bindUpdate(PreparedStatement stmt, ClassDescriptor cld, Object obj) throws java.sql.SQLException 490 { 491 if (cld.getUpdateProcedure() != null) 492 { 493 this.bindProcedure(stmt, cld, obj, cld.getUpdateProcedure()); 494 } 495 else 496 { 497 int index = 1; 498 ValueContainer[] values, valuesSnapshot; 499 valuesSnapshot = cld.getCurrentLockingValues(obj); 501 cld.updateLockingValues(obj); values = getNonKeyValues(m_broker, cld, obj); 503 504 for (int i = 0; i < values.length; i++) 506 { 507 setObjectForStatement(stmt, index, values[i].getValue(), values[i].getJdbcType().getType()); 508 index++; 509 } 510 values = getKeyValues(m_broker, cld, obj); 512 for (int i = 0; i < values.length; i++) 513 { 514 setObjectForStatement(stmt, index, values[i].getValue(), values[i].getJdbcType().getType()); 515 index++; 516 } 517 values = valuesSnapshot; 520 for (int i = 0; i < values.length; i++) 521 { 522 setObjectForStatement(stmt, index, values[i].getValue(), values[i].getJdbcType().getType()); 523 index++; 524 } 525 } 526 } 527 528 533 public int bindValues(PreparedStatement stmt, ValueContainer[] values, int index) throws SQLException 534 { 535 if (values != null) 536 { 537 for (int i = 0; i < values.length; i++) 538 { 539 setObjectForStatement(stmt, index, values[i].getValue(), values[i].getJdbcType().getType()); 540 index++; 541 } 542 } 543 return index; 544 } 545 546 549 public PreparedStatement getDeleteStatement(ClassDescriptor cld) throws PersistenceBrokerSQLException, PersistenceBrokerException 550 { 551 try 552 { 553 return cld.getStatementsForClass(m_conMan).getDeleteStmt(m_conMan.getConnection()); 554 } 555 catch (SQLException e) 556 { 557 throw new PersistenceBrokerSQLException("Could not build statement ask for", e); 558 } 559 catch (LookupException e) 560 { 561 throw new PersistenceBrokerException("Used ConnectionManager instance could not obtain a connection", e); 562 } 563 } 564 565 569 public Statement getGenericStatement(ClassDescriptor cds, boolean scrollable) throws PersistenceBrokerException 570 { 571 try 572 { 573 return cds.getStatementsForClass(m_conMan).getGenericStmt(m_conMan.getConnection(), scrollable); 574 } 575 catch (LookupException e) 576 { 577 throw new PersistenceBrokerException("Used ConnectionManager instance could not obtain a connection", e); 578 } 579 } 580 581 584 public PreparedStatement getInsertStatement(ClassDescriptor cds) throws PersistenceBrokerSQLException, PersistenceBrokerException 585 { 586 try 587 { 588 return cds.getStatementsForClass(m_conMan).getInsertStmt(m_conMan.getConnection()); 589 } 590 catch (SQLException e) 591 { 592 throw new PersistenceBrokerSQLException("Could not build statement ask for", e); 593 } 594 catch (LookupException e) 595 { 596 throw new PersistenceBrokerException("Used ConnectionManager instance could not obtain a connection", e); 597 } 598 } 599 600 603 public PreparedStatement getPreparedStatement(ClassDescriptor cds, String sql, 604 boolean scrollable, int explicitFetchSizeHint, boolean callableStmt) 605 throws PersistenceBrokerException 606 { 607 try 608 { 609 return cds.getStatementsForClass(m_conMan).getPreparedStmt(m_conMan.getConnection(), sql, scrollable, explicitFetchSizeHint, callableStmt); 610 } 611 catch (LookupException e) 612 { 613 throw new PersistenceBrokerException("Used ConnectionManager instance could not obtain a connection", e); 614 } 615 } 616 617 620 public PreparedStatement getSelectByPKStatement(ClassDescriptor cds) throws PersistenceBrokerSQLException, PersistenceBrokerException 621 { 622 try 623 { 624 return cds.getStatementsForClass(m_conMan).getSelectByPKStmt(m_conMan.getConnection()); 625 } 626 catch (SQLException e) 627 { 628 throw new PersistenceBrokerSQLException("Could not build statement ask for", e); 629 } 630 catch (LookupException e) 631 { 632 throw new PersistenceBrokerException("Used ConnectionManager instance could not obtain a connection", e); 633 } 634 } 635 636 639 public PreparedStatement getUpdateStatement(ClassDescriptor cds) throws PersistenceBrokerSQLException, PersistenceBrokerException 640 { 641 try 642 { 643 return cds.getStatementsForClass(m_conMan).getUpdateStmt(m_conMan.getConnection()); 644 } 645 catch (SQLException e) 646 { 647 throw new PersistenceBrokerSQLException("Could not build statement ask for", e); 648 } 649 catch (LookupException e) 650 { 651 throw new PersistenceBrokerException("Used ConnectionManager instance could not obtain a connection", e); 652 } 653 } 654 655 659 protected ValueContainer[] getAllValues(ClassDescriptor cld, Object obj) throws PersistenceBrokerException 660 { 661 return m_broker.serviceBrokerHelper().getAllRwValues(cld, obj); 662 } 663 664 668 protected ValueContainer[] getKeyValues(PersistenceBroker broker, ClassDescriptor cld, Object obj) throws PersistenceBrokerException 669 { 670 return broker.serviceBrokerHelper().getKeyValues(cld, obj); 671 } 672 673 677 protected ValueContainer[] getKeyValues(PersistenceBroker broker, ClassDescriptor cld, Identity oid) throws PersistenceBrokerException 678 { 679 return broker.serviceBrokerHelper().getKeyValues(cld, oid); 680 } 681 682 686 protected ValueContainer[] getNonKeyValues(PersistenceBroker broker, ClassDescriptor cld, Object obj) throws PersistenceBrokerException 687 { 688 return broker.serviceBrokerHelper().getNonKeyRwValues(cld, obj); 689 } 690 691 704 private void bindProcedure(PreparedStatement stmt, ClassDescriptor cld, Object obj, ProcedureDescriptor proc) 705 throws SQLException 706 { 707 int valueSub = 0; 708 709 CallableStatement callable = null; 712 try 713 { 714 callable = (CallableStatement ) stmt; 715 } 716 catch(Exception e) 717 { 718 m_log.error("Error while bind values for class '" + (cld != null ? cld.getClassNameOfObject() : null) 719 + "', using stored procedure: "+ proc, e); 720 if(e instanceof SQLException ) 721 { 722 throw (SQLException ) e; 723 } 724 else 725 { 726 throw new PersistenceBrokerException("Unexpected error while bind values for class '" 727 + (cld != null ? cld.getClassNameOfObject() : null) + "', using stored procedure: "+ proc); 728 } 729 } 730 731 if ((proc.hasReturnValue()) && (callable != null)) 733 { 734 int jdbcType = proc.getReturnValueFieldRef().getJdbcType().getType(); 735 m_platform.setNullForStatement(stmt, valueSub + 1, jdbcType); 736 callable.registerOutParameter(valueSub + 1, jdbcType); 737 valueSub++; 738 } 739 740 Iterator iterator = proc.getArguments().iterator(); 742 while (iterator.hasNext()) 743 { 744 ArgumentDescriptor arg = (ArgumentDescriptor) iterator.next(); 745 Object val = arg.getValue(obj); 746 int jdbcType = arg.getJdbcType(); 747 setObjectForStatement(stmt, valueSub + 1, val, jdbcType); 748 if ((arg.getIsReturnedByProcedure()) && (callable != null)) 749 { 750 callable.registerOutParameter(valueSub + 1, jdbcType); 751 } 752 valueSub++; 753 } 754 } 755 756 764 private void setObjectForStatement(PreparedStatement stmt, int index, Object value, int sqlType) 765 throws SQLException 766 { 767 if (value == null) 768 { 769 m_platform.setNullForStatement(stmt, index, sqlType); 770 } 771 else 772 { 773 m_platform.setObjectForStatement(stmt, index, value, sqlType); 774 } 775 } 776 777 } 778 | Popular Tags |