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.util.HashMap ; 23 import java.util.Iterator ; 24 import java.util.Map ; 25 26 import org.apache.ojb.broker.Identity; 27 import org.apache.ojb.broker.OptimisticLockException; 28 import org.apache.ojb.broker.PersistenceBroker; 29 import org.apache.ojb.broker.PersistenceBrokerException; 30 import org.apache.ojb.broker.PersistenceBrokerSQLException; 31 import org.apache.ojb.broker.accesslayer.sql.SelectStatement; 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.JdbcType; 37 import org.apache.ojb.broker.metadata.ProcedureDescriptor; 38 import org.apache.ojb.broker.metadata.fieldaccess.PersistentField; 39 import org.apache.ojb.broker.platforms.Platform; 40 import org.apache.ojb.broker.query.Query; 41 import org.apache.ojb.broker.util.ExceptionHelper; 42 import org.apache.ojb.broker.util.logging.Logger; 43 import org.apache.ojb.broker.util.logging.LoggerFactory; 44 import org.apache.ojb.broker.util.sequence.SequenceManagerException; 45 46 54 public class JdbcAccessImpl implements JdbcAccess 55 { 56 59 protected Logger logger; 60 61 64 protected PersistenceBroker broker; 65 66 70 public JdbcAccessImpl(PersistenceBroker broker) 71 { 72 this.broker = broker; 73 logger = LoggerFactory.getLogger(this.getClass()); 74 } 75 76 81 private Platform getPlatform() 82 { 83 return this.broker.serviceConnectionManager().getSupportedPlatform(); 84 } 85 86 91 public void executeDelete(ClassDescriptor cld, Object obj) throws PersistenceBrokerException 92 { 93 if (logger.isDebugEnabled()) 94 { 95 logger.debug("executeDelete: " + obj); 96 } 97 98 final StatementManagerIF sm = broker.serviceStatementManager(); 99 PreparedStatement stmt = null; 100 try 101 { 102 stmt = sm.getDeleteStatement(cld); 103 if (stmt == null) 104 { 105 logger.error("getDeleteStatement returned a null statement"); 106 throw new PersistenceBrokerException("JdbcAccessImpl: getDeleteStatement returned a null statement"); 107 } 108 109 sm.bindDelete(stmt, cld, obj); 110 if (logger.isDebugEnabled()) 111 logger.debug("executeDelete: " + stmt); 112 113 if (stmt.executeUpdate() == 0 && cld.isLocking()) { 119 throw new OptimisticLockException("Object has been modified or deleted by someone else", obj); 120 } 121 122 harvestReturnValues(cld.getDeleteProcedure(), obj, stmt); 124 } 125 catch (OptimisticLockException e) 126 { 127 if (logger.isDebugEnabled()) 129 logger.debug("OptimisticLockException during the execution of delete: " 130 + e.getMessage(), e); 131 throw e; 132 } 133 catch (PersistenceBrokerException e) 134 { 135 logger.error("PersistenceBrokerException during the execution of delete: " 136 + e.getMessage(), e); 137 throw e; 138 } 139 catch (SQLException e) 140 { 141 final String sql = broker.serviceSqlGenerator().getPreparedDeleteStatement(cld).getStatement(); 142 throw ExceptionHelper.generateException(e, sql, cld, logger, obj); 143 } 144 finally 145 { 146 sm.closeResources(stmt, null); 147 } 148 } 149 150 155 public void executeDelete(Query query, ClassDescriptor cld) throws PersistenceBrokerException 156 { 157 if (logger.isDebugEnabled()) 158 { 159 logger.debug("executeDelete (by Query): " + query); 160 } 161 final StatementManagerIF sm = broker.serviceStatementManager(); 162 PreparedStatement stmt = null; 163 final String sql = this.broker.serviceSqlGenerator().getPreparedDeleteStatement(query, cld).getStatement(); 164 try 165 { 166 stmt = sm.getPreparedStatement(cld, sql, 167 false, StatementManagerIF.FETCH_SIZE_NOT_APPLICABLE, cld.getDeleteProcedure()!=null); 168 169 sm.bindStatement(stmt, query, cld, 1); 170 if (logger.isDebugEnabled()) 171 logger.debug("executeDelete (by Query): " + stmt); 172 173 stmt.executeUpdate(); 174 } 175 catch (SQLException e) 176 { 177 throw ExceptionHelper.generateException(e, sql, cld, null, logger); 178 } 179 finally 180 { 181 sm.closeResources(stmt, null); 182 } 183 } 184 185 190 public void executeInsert(ClassDescriptor cld, Object obj) throws PersistenceBrokerException 191 { 192 if (logger.isDebugEnabled()) 193 { 194 logger.debug("executeInsert: " + obj); 195 } 196 final StatementManagerIF sm = broker.serviceStatementManager(); 197 PreparedStatement stmt = null; 198 try 199 { 200 stmt = sm.getInsertStatement(cld); 201 if (stmt == null) 202 { 203 logger.error("getInsertStatement returned a null statement"); 204 throw new PersistenceBrokerException("getInsertStatement returned a null statement"); 205 } 206 assignAutoincrementSequences(cld, obj); 208 sm.bindInsert(stmt, cld, obj); 209 if (logger.isDebugEnabled()) 210 logger.debug("executeInsert: " + stmt); 211 stmt.executeUpdate(); 212 assignAutoincrementIdentityColumns(cld, obj); 214 215 harvestReturnValues(cld.getInsertProcedure(), obj, stmt); 217 } 218 catch (PersistenceBrokerException e) 219 { 220 logger.error("PersistenceBrokerException during the execution of the insert: " + e.getMessage(), e); 221 throw e; 222 } 223 catch(SequenceManagerException e) 224 { 225 throw new PersistenceBrokerException("Error while try to assign identity value", e); 226 } 227 catch (SQLException e) 228 { 229 final String sql = broker.serviceSqlGenerator().getPreparedInsertStatement(cld).getStatement(); 230 throw ExceptionHelper.generateException(e, sql, cld, logger, obj); 231 } 232 finally 233 { 234 sm.closeResources(stmt, null); 235 } 236 } 237 238 243 public ResultSetAndStatement executeQuery(Query query, ClassDescriptor cld) throws PersistenceBrokerException 244 { 245 if (logger.isDebugEnabled()) 246 { 247 logger.debug("executeQuery: " + query); 248 } 249 253 boolean scrollable = ((query.getStartAtIndex() > Query.NO_START_AT_INDEX) || (query.getEndAtIndex() > Query.NO_END_AT_INDEX)); 254 257 if (query != null && query.getPrefetchedRelationships() != null && !query.getPrefetchedRelationships().isEmpty()) 258 { 259 scrollable = true; 260 } 261 final StatementManagerIF sm = broker.serviceStatementManager(); 262 final SelectStatement sql = broker.serviceSqlGenerator().getPreparedSelectStatement(query, cld); 263 PreparedStatement stmt = null; 264 ResultSet rs = null; 265 try 266 { 267 final int queryFetchSize = query.getFetchSize(); 268 final boolean isStoredProcedure = isStoredProcedure(sql.getStatement()); 269 stmt = sm.getPreparedStatement(cld, sql.getStatement() , 270 scrollable, queryFetchSize, isStoredProcedure); 271 if (isStoredProcedure) 272 { 273 getPlatform().registerOutResultSet((CallableStatement ) stmt, 1); 276 sm.bindStatement(stmt, query, cld, 2); 277 278 if (logger.isDebugEnabled()) 279 logger.debug("executeQuery: " + stmt); 280 281 stmt.execute(); 282 rs = (ResultSet ) ((CallableStatement ) stmt).getObject(1); 283 } 284 else 285 { 286 sm.bindStatement(stmt, query, cld, 1); 287 288 if (logger.isDebugEnabled()) 289 logger.debug("executeQuery: " + stmt); 290 291 rs = stmt.executeQuery(); 292 } 293 294 return new ResultSetAndStatement(sm, stmt, rs, sql); 295 } 296 catch (PersistenceBrokerException e) 297 { 298 sm.closeResources(stmt, rs); 300 logger.error("PersistenceBrokerException during the execution of the query: " + e.getMessage(), e); 301 throw e; 302 } 303 catch (SQLException e) 304 { 305 sm.closeResources(stmt, rs); 307 throw ExceptionHelper.generateException(e, sql.getStatement(), null, logger, null); 308 } 309 } 310 311 public ResultSetAndStatement executeSQL( 312 String sqlStatement, 313 ClassDescriptor cld, 314 boolean scrollable) 315 throws PersistenceBrokerException 316 { 317 return executeSQL(sqlStatement, cld, null, scrollable); 318 } 319 320 325 public ResultSetAndStatement executeSQL( 326 final String sql, 327 ClassDescriptor cld, 328 ValueContainer[] values, 329 boolean scrollable) 330 throws PersistenceBrokerException 331 { 332 if (logger.isDebugEnabled()) logger.debug("executeSQL: " + sql); 333 final boolean isStoredprocedure = isStoredProcedure(sql); 334 final StatementManagerIF sm = broker.serviceStatementManager(); 335 PreparedStatement stmt = null; 336 ResultSet rs = null; 337 try 338 { 339 stmt = sm.getPreparedStatement(cld, sql, 340 scrollable, StatementManagerIF.FETCH_SIZE_NOT_EXPLICITLY_SET, isStoredprocedure); 341 if (isStoredprocedure) 342 { 343 getPlatform().registerOutResultSet((CallableStatement ) stmt, 1); 346 sm.bindValues(stmt, values, 2); 347 stmt.execute(); 348 rs = (ResultSet ) ((CallableStatement ) stmt).getObject(1); 349 } 350 else 351 { 352 sm.bindValues(stmt, values, 1); 353 rs = stmt.executeQuery(); 354 } 355 356 return new ResultSetAndStatement(sm, stmt, rs, new SelectStatement() 359 { 360 public Query getQueryInstance() 361 { 362 return null; 363 } 364 365 public int getColumnIndex(FieldDescriptor fld) 366 { 367 return JdbcType.MIN_INT; 368 } 369 370 public String getStatement() 371 { 372 return sql; 373 } 374 }); 375 } 376 catch (PersistenceBrokerException e) 377 { 378 sm.closeResources(stmt, rs); 380 logger.error("PersistenceBrokerException during the execution of the SQL query: " + e.getMessage(), e); 381 throw e; 382 } 383 catch (SQLException e) 384 { 385 sm.closeResources(stmt, rs); 387 throw ExceptionHelper.generateException(e, sql, cld, values, logger, null); 388 } 389 } 390 391 public int executeUpdateSQL(String sqlStatement, ClassDescriptor cld) 392 throws PersistenceBrokerException 393 { 394 return executeUpdateSQL(sqlStatement, cld, null, null); 395 } 396 397 403 public int executeUpdateSQL( 404 String sqlStatement, 405 ClassDescriptor cld, 406 ValueContainer[] values1, 407 ValueContainer[] values2) 408 throws PersistenceBrokerException 409 { 410 if (logger.isDebugEnabled()) 411 logger.debug("executeUpdateSQL: " + sqlStatement); 412 413 int result; 414 int index; 415 PreparedStatement stmt = null; 416 final StatementManagerIF sm = broker.serviceStatementManager(); 417 try 418 { 419 stmt = sm.getPreparedStatement(cld, sqlStatement, 420 Query.NOT_SCROLLABLE, StatementManagerIF.FETCH_SIZE_NOT_APPLICABLE, isStoredProcedure(sqlStatement)); 421 index = sm.bindValues(stmt, values1, 1); 422 sm.bindValues(stmt, values2, index); 423 result = stmt.executeUpdate(); 424 } 425 catch (PersistenceBrokerException e) 426 { 427 logger.error("PersistenceBrokerException during the execution of the Update SQL query: " + e.getMessage(), e); 428 throw e; 429 } 430 catch (SQLException e) 431 { 432 ValueContainer[] tmp = addValues(values1, values2); 433 throw ExceptionHelper.generateException(e, sqlStatement, cld, tmp, logger, null); 434 } 435 finally 436 { 437 sm.closeResources(stmt, null); 438 } 439 return result; 440 } 441 442 443 private ValueContainer[] addValues(ValueContainer[] target, ValueContainer[] source) 444 { 445 ValueContainer[] newArray; 446 if(source != null && source.length > 0) 447 { 448 if(target != null) 449 { 450 newArray = new ValueContainer[target.length + source.length]; 451 System.arraycopy(target, 0, newArray, 0, target.length); 452 System.arraycopy(source, 0, newArray, target.length, source.length); 453 } 454 else 455 { 456 newArray = source; 457 } 458 } 459 else 460 { 461 newArray = target; 462 } 463 return newArray; 464 } 465 466 471 public void executeUpdate(ClassDescriptor cld, Object obj) throws PersistenceBrokerException 472 { 473 if (logger.isDebugEnabled()) 474 { 475 logger.debug("executeUpdate: " + obj); 476 } 477 478 if (cld.getNonPkRwFields().length == 0) 480 { 481 return; 482 } 483 484 final StatementManagerIF sm = broker.serviceStatementManager(); 485 PreparedStatement stmt = null; 486 ValueContainer[] oldLockingValues; 489 oldLockingValues = cld.getCurrentLockingValues(obj); 490 try 491 { 492 stmt = sm.getUpdateStatement(cld); 493 if (stmt == null) 494 { 495 logger.error("getUpdateStatement returned a null statement"); 496 throw new PersistenceBrokerException("getUpdateStatement returned a null statement"); 497 } 498 499 sm.bindUpdate(stmt, cld, obj); 500 if (logger.isDebugEnabled()) 501 logger.debug("executeUpdate: " + stmt); 502 503 if ((stmt.executeUpdate() == 0) && cld.isLocking()) { 505 throw new OptimisticLockException("Object has been modified by someone else", obj); 506 } 507 508 harvestReturnValues(cld.getUpdateProcedure(), obj, stmt); 510 } 511 catch (OptimisticLockException e) 512 { 513 if (logger.isDebugEnabled()) 515 logger.debug( 516 "OptimisticLockException during the execution of update: " + e.getMessage(), 517 e); 518 throw e; 519 } 520 catch (PersistenceBrokerException e) 521 { 522 setLockingValues(cld, obj, oldLockingValues); 524 525 logger.error( 526 "PersistenceBrokerException during the execution of the update: " + e.getMessage(), 527 e); 528 throw e; 529 } 530 catch (SQLException e) 531 { 532 final String sql = broker.serviceSqlGenerator().getPreparedUpdateStatement(cld).getStatement(); 533 throw ExceptionHelper.generateException(e, sql, cld, logger, obj); 534 } 535 finally 536 { 537 sm.closeResources(stmt, null); 538 } 539 } 540 541 550 public Object materializeObject(ClassDescriptor cld, Identity oid) 551 throws PersistenceBrokerException 552 { 553 final StatementManagerIF sm = broker.serviceStatementManager(); 554 final SelectStatement sql = broker.serviceSqlGenerator().getPreparedSelectByPkStatement(cld); 555 Object result = null; 556 PreparedStatement stmt = null; 557 ResultSet rs = null; 558 try 559 { 560 stmt = sm.getSelectByPKStatement(cld); 561 if (stmt == null) 562 { 563 logger.error("getSelectByPKStatement returned a null statement"); 564 throw new PersistenceBrokerException("getSelectByPKStatement returned a null statement"); 565 } 566 570 sm.bindSelect(stmt, oid, cld, false); 571 rs = stmt.executeQuery(); 572 ResultSetAndStatement rs_stmt = new ResultSetAndStatement(broker.serviceStatementManager(), stmt, rs, sql); 574 if (rs.next()) 575 { 576 Map row = new HashMap (); 577 cld.getRowReader().readObjectArrayFrom(rs_stmt, row); 578 result = cld.getRowReader().readObjectFrom(row); 579 } 580 rs_stmt.close(); 582 } 583 catch (PersistenceBrokerException e) 584 { 585 sm.closeResources(stmt, rs); 587 logger.error("PersistenceBrokerException during the execution of materializeObject: " + e.getMessage(), e); 588 throw e; 589 } 590 catch (SQLException e) 591 { 592 sm.closeResources(stmt, rs); 594 throw ExceptionHelper.generateException(e, sql.getStatement(), cld, logger, null); 595 } 596 return result; 597 } 598 599 605 private void setLockingValues(ClassDescriptor cld, Object obj, ValueContainer[] oldLockingValues) 606 { 607 FieldDescriptor fields[] = cld.getLockingFields(); 608 609 for (int i=0; i<fields.length; i++) 610 { 611 PersistentField field = fields[i].getPersistentField(); 612 Object lockVal = oldLockingValues[i].getValue(); 613 614 field.set(obj, lockVal); 615 } 616 } 617 618 629 private void harvestReturnValues( 630 ProcedureDescriptor proc, 631 Object obj, 632 PreparedStatement stmt) 633 throws PersistenceBrokerSQLException 634 { 635 if ((proc == null) || (!proc.hasReturnValues())) 638 { 639 return; 640 } 641 642 CallableStatement callable = (CallableStatement ) stmt; 644 645 int index = 0; 647 648 if (proc.hasReturnValue()) 650 { 651 652 index++; 654 655 this.harvestReturnValue(obj, callable, proc.getReturnValueFieldRef(), index); 657 } 658 659 Iterator iter = proc.getArguments().iterator(); 662 while (iter.hasNext()) 663 { 664 index++; 665 ArgumentDescriptor arg = (ArgumentDescriptor) iter.next(); 666 if (arg.getIsReturnedByProcedure()) 667 { 668 this.harvestReturnValue(obj, callable, arg.getFieldRef(), index); 669 } 670 } 671 } 672 673 684 private void harvestReturnValue( 685 Object obj, 686 CallableStatement callable, 687 FieldDescriptor fmd, 688 int index) 689 throws PersistenceBrokerSQLException 690 { 691 692 try 693 { 694 if ((callable != null) && (fmd != null) && (obj != null)) 697 { 698 Object value = fmd.getJdbcType().getObjectFromColumn(callable, index); 701 702 fmd.getPersistentField().set(obj, fmd.getFieldConversion().sqlToJava(value)); 704 705 } 706 } 707 catch (SQLException e) 708 { 709 String msg = "SQLException during the execution of harvestReturnValue" 710 + " class=" 711 + obj.getClass().getName() 712 + "," 713 + " field=" 714 + fmd.getAttributeName() 715 + " : " 716 + e.getMessage(); 717 logger.error(msg,e); 718 throw new PersistenceBrokerSQLException(msg, e); 719 } 720 } 721 722 728 protected boolean isStoredProcedure(String sql) 729 { 730 739 int k = 0, i = 0; 740 char c; 741 while(k < 3 && i < sql.length()) 742 { 743 c = sql.charAt(i); 744 if(c != ' ') 745 { 746 switch (k) 747 { 748 case 0: 749 if(c != '{') return false; 750 break; 751 case 1: 752 if(c != '?' && c != 'c') return false; 753 break; 754 case 2: 755 if(c != '=' && c != 'a') return false; 756 break; 757 } 758 k++; 759 } 760 i++; 761 } 762 return true; 763 } 764 765 protected void assignAutoincrementSequences(ClassDescriptor cld, Object target) throws SequenceManagerException 766 { 767 FieldDescriptor[] fields = cld.getFieldDescriptor(false); 770 FieldDescriptor field; 771 for(int i = 0; i < fields.length; i++) 772 { 773 field = fields[i]; 774 if(field.isAutoIncrement() && !field.isAccessReadOnly()) 775 { 776 Object value = field.getPersistentField().get(target); 777 if(broker.serviceBrokerHelper().representsNull(field, value)) 778 { 779 Object id = broker.serviceSequenceManager().getUniqueValue(field); 780 field.getPersistentField().set(target, id); 781 } 782 } 783 } 784 } 785 786 protected void assignAutoincrementIdentityColumns(ClassDescriptor cld, Object target) throws SequenceManagerException 787 { 788 if(cld.useIdentityColumnField()) broker.serviceSequenceManager().afterStore(this, cld, target); 791 } 792 } 793 | Popular Tags |