1 24 package org.ofbiz.entity.jdbc; 25 26 import java.io.ByteArrayInputStream ; 27 import java.io.ByteArrayOutputStream ; 28 import java.io.IOException ; 29 import java.io.ObjectOutputStream ; 30 import java.math.BigDecimal ; 31 import java.sql.*; 32 import java.util.ArrayList ; 33 import java.util.List ; 34 import java.util.Map ; 35 36 import org.ofbiz.base.util.Debug; 37 import org.ofbiz.entity.GenericDataSourceException; 38 import org.ofbiz.entity.GenericEntityException; 39 import org.ofbiz.entity.config.DatasourceInfo; 40 import org.ofbiz.entity.config.EntityConfigUtil; 41 import org.ofbiz.entity.transaction.GenericTransactionException; 42 import org.ofbiz.entity.transaction.TransactionUtil; 43 44 52 public class SQLProcessor { 53 54 55 public static final String module = SQLProcessor.class.getName(); 56 57 58 public static List CONNECTION_TEST_LIST = new ArrayList (); 59 public static int MAX_CONNECTIONS = 1000; 60 public static boolean ENABLE_TEST = false; 61 62 63 private String helperName; 64 65 private Connection _connection = null; 67 68 private PreparedStatement _ps = null; 70 71 private Statement _stmt = null; 73 74 private ResultSet _rs = null; 76 77 private ResultSetMetaData _rsmd = null; 78 79 private String _sql; 81 82 private int _ind; 84 85 private boolean _manualTX; 87 88 private boolean _bDeleteConnection = false; 90 91 private Map _needClobWorkAroundWrite = null; 92 private Map _needBlobWorkAroundWrite = null; 93 94 99 public SQLProcessor(String helperName) { 100 this.helperName = helperName; 101 this._manualTX = true; 102 } 103 104 111 public SQLProcessor(String helperName, Connection connection) { 112 this.helperName = helperName; 113 this._connection = connection; 114 115 if (_connection != null) { 117 _manualTX = false; 118 } 119 } 120 121 ResultSetMetaData getResultSetMetaData() { 122 if (_rsmd == null) { 123 try { 125 if (_rs != null) { 126 _rsmd = _rs.getMetaData(); 127 } else if (_ps != null) { 128 _rsmd = _ps.getMetaData(); 129 } 130 } catch (SQLException sqle2) { 131 Debug.logWarning("[SQLProcessor.rollback]: SQL Exception while rolling back insert. Error was:" + sqle2, module); 132 Debug.logWarning(sqle2, module); 133 } 134 } 135 return _rsmd; 136 } 137 138 143 public void commit() throws GenericDataSourceException { 144 if (_connection == null) { 145 return; 146 } 147 148 if (Debug.verboseOn()) Debug.logVerbose("SQLProcessor:commit() _manualTX=" + _manualTX, module); 149 150 if (_manualTX) { 151 try { 152 _connection.commit(); 153 if (Debug.verboseOn()) Debug.logVerbose("SQLProcessor:commit() : called commit on connection", module); 154 } catch (SQLException sqle) { 155 Debug.logError(sqle, "Error committing transaction: " + sqle.toString()); 156 try { 157 rollback(); 158 } catch (GenericDataSourceException rbsqle) { 159 Debug.logError(rbsqle, "Got another error when trying to rollback after error committing transaction: " + sqle.toString()); 160 } 161 throw new GenericDataSourceException("SQL Exception occurred on commit", sqle); 162 } 163 } 164 } 165 166 169 public void rollback() throws GenericDataSourceException { 170 if (_connection == null) { 171 return; 172 } 173 174 if (Debug.verboseOn()) Debug.logVerbose("SQLProcessor:rollback() _manualTX=" + _manualTX, module); 175 176 try { 177 if (_manualTX) { 178 _connection.rollback(); 179 if (Debug.verboseOn()) Debug.logVerbose("SQLProcessor:rollback() : _manualTX=" + _manualTX, module); 180 } else { 181 try { 182 TransactionUtil.setRollbackOnly("rollback called in Entity Engine SQLProcessor", new Exception ("Current Location Stack")); 183 if (Debug.verboseOn()) Debug.logVerbose("SQLProcessor:rollback() : _manualTX=" + _manualTX, module); 184 } catch (GenericTransactionException e) { 185 Debug.logError(e, "Error setting rollback only", module); 186 throw new GenericDataSourceException("Error setting rollback only", e); 187 } 188 } 189 } catch (SQLException sqle2) { 190 Debug.logWarning("[SQLProcessor.rollback]: SQL Exception while rolling back insert. Error was:" + sqle2, module); 191 Debug.logWarning(sqle2, module); 192 } 193 } 194 195 200 public void close() throws GenericDataSourceException { 201 if (_manualTX) { 202 if (Debug.verboseOn()) Debug.logVerbose("SQLProcessor:close() calling commit : _manualTX=" + _manualTX, module); 203 commit(); 204 } 205 206 _sql = null; 207 208 if (_rs != null) { 209 try { 210 _rs.close(); 211 if (Debug.verboseOn()) Debug.logVerbose("SQLProcessor:close() result close : _manualTX=" + _manualTX, module); 212 } catch (SQLException sqle) { 213 Debug.logWarning(sqle.getMessage(), module); 214 } 215 216 _rs = null; 217 } 218 219 if (_ps != null) { 220 try { 221 _ps.close(); 222 if (Debug.verboseOn()) Debug.logVerbose("SQLProcessor:close() preparedStatement close : _manualTX=" + _manualTX, module); 223 } catch (SQLException sqle) { 224 Debug.logWarning(sqle.getMessage(), module); 225 } 226 227 _ps = null; 228 } 229 230 if (_stmt != null) { 231 try { 232 _stmt.close(); 233 if (Debug.verboseOn()) Debug.logVerbose("SQLProcessor:close() statement close : _manualTX=" + _manualTX, module); 234 } catch (SQLException sqle) { 235 Debug.logWarning(sqle.getMessage(), module); 236 } 237 238 _stmt = null; 239 } 240 241 if ((_connection != null) && _bDeleteConnection) { 242 try { 243 _connection.close(); 244 if (Debug.verboseOn()) Debug.logVerbose("SQLProcessor:close() connection close : _manualTX=" + _manualTX, module); 245 } catch (SQLException sqle) { 246 Debug.logWarning(sqle.getMessage(), module); 247 } 248 249 _connection = null; 250 } 251 } 252 253 261 public Connection getConnection() throws GenericDataSourceException, GenericEntityException { 262 if (_connection != null) 263 return _connection; 264 265 _manualTX = true; 266 267 try { 268 _connection = ConnectionFactory.getConnection(helperName); 269 if (Debug.verboseOn()) Debug.logVerbose("SQLProcessor:connection() : manualTx=" + _manualTX, module); 270 } catch (SQLException sqle) { 271 throw new GenericDataSourceException("Unable to esablish a connection with the database.", sqle); 272 } 273 274 if (_connection == null) { 276 throw new GenericDataSourceException("Unable to esablish a connection with the database. Connection was null!"); 277 } 278 279 testConnection(_connection); 281 282 303 304 try { 306 if (_connection.getAutoCommit()) { 307 try { 308 _connection.setAutoCommit(false); 309 if (Debug.verboseOn()) Debug.logVerbose("SQLProcessor:setAutoCommit(false) : manualTx=" + _manualTX, module); 310 } catch (SQLException sqle) { 311 _manualTX = false; 312 } 313 } 314 } catch (SQLException e) { 315 throw new GenericDataSourceException("Cannot get autoCommit status from connection", e); 316 } 317 318 try { 319 if (TransactionUtil.getStatus() == TransactionUtil.STATUS_ACTIVE) { 320 if (Debug.verboseOn()) Debug.logVerbose("[SQLProcessor.getConnection] : active transaction", module); 321 _manualTX = false; 322 } 323 } catch (GenericTransactionException e) { 324 Debug.logWarning("[SQLProcessor.getConnection]: Exception was thrown trying to check " + 326 "transaction status: " + e.toString(), module); 327 } 328 329 if (Debug.verboseOn()) Debug.logVerbose("[SQLProcessor.getConnection] : con=" + _connection, module); 330 331 _bDeleteConnection = true; 332 return _connection; 333 } 334 335 344 public void prepareStatement(String sql) throws GenericDataSourceException, GenericEntityException { 345 this.prepareStatement(sql, false, 0, 0, -1, -1); 346 } 347 348 357 public void prepareStatement(String sql, boolean specifyTypeAndConcur, int resultSetType, int resultSetConcurrency) throws GenericDataSourceException, GenericEntityException { 358 this.prepareStatement(sql, specifyTypeAndConcur, resultSetType, resultSetConcurrency, -1, -1); 359 } 360 361 370 public void prepareStatement(String sql, boolean specifyTypeAndConcur, int resultSetType, int resultSetConcurrency, int fetchSize, int maxRows) throws GenericDataSourceException, GenericEntityException { 371 if (Debug.verboseOn()) Debug.logVerbose("[SQLProcessor.prepareStatement] sql=" + sql, module); 372 373 if (_connection == null) { 374 getConnection(); 375 } 376 377 try { 378 _sql = sql; 379 _ind = 1; 380 if (specifyTypeAndConcur) { 381 _ps = _connection.prepareStatement(sql, resultSetType, resultSetConcurrency); 382 if (Debug.verboseOn()) Debug.logVerbose("[SQLProcessor.prepareStatement] _ps=" + _ps, module); 383 } else { 384 _ps = _connection.prepareStatement(sql); 385 if (Debug.verboseOn()) Debug.logVerbose("[SQLProcessor.prepareStatement] (def) _ps=" + _ps, module); 386 } 387 if (maxRows > 0) { 388 _ps.setMaxRows(maxRows); 389 if (Debug.verboseOn()) Debug.logVerbose("[SQLProcessor.prepareStatement] max rows set : " + maxRows, module); 390 } 391 this.setFetchSize(_ps, fetchSize); 392 } catch (SQLException sqle) { 393 throw new GenericDataSourceException("SQL Exception while executing the following:" + sql, sqle); 394 } 395 } 396 397 403 public ResultSet executeQuery() throws GenericDataSourceException { 404 try { 405 _rs = _ps.executeQuery(); 407 } catch (SQLException sqle) { 408 throw new GenericDataSourceException("SQL Exception while executing the following:" + _sql, sqle); 409 } 410 411 return _rs; 412 } 413 414 422 public ResultSet executeQuery(String sql) throws GenericDataSourceException, GenericEntityException { 423 prepareStatement(sql); 424 return executeQuery(); 425 } 426 427 433 public int executeUpdate() throws GenericDataSourceException { 434 try { 435 return _ps.executeUpdate(); 437 } catch (SQLException sqle) { 438 throw new GenericDataSourceException("SQL Exception while executing the following:" + _sql, sqle); 440 } 441 } 442 443 449 public int executeUpdate(String sql) throws GenericDataSourceException { 450 Statement stmt = null; 451 452 try { 453 stmt = _connection.createStatement(); 454 return stmt.executeUpdate(sql); 455 } catch (SQLException sqle) { 456 Debug.logError(sqle, "SQLProcessor.executeUpdate(sql) : ERROR : ", module); 457 throw new GenericDataSourceException("SQL Exception while executing the following:" + _sql, sqle); 458 } finally { 459 if (stmt != null) { 460 try { 461 stmt.close(); 462 } catch (SQLException sqle) { 463 Debug.logWarning("Unable to close 'statement': " + sqle.getMessage(), module); 464 } 465 } 466 } 467 } 468 469 476 public boolean next() throws GenericDataSourceException { 477 try { 478 return _rs.next(); 479 } catch (SQLException sqle) { 480 throw new GenericDataSourceException("SQL Exception while executing the following:" + _sql, sqle); 481 } 482 } 483 484 489 public ResultSet getResultSet() { 490 return _rs; 491 } 492 493 498 public PreparedStatement getPreparedStatement() { 499 return _ps; 500 } 501 502 511 public void execQuery(String sql, ExecQueryCallbackFunctionIF aListener) throws GenericEntityException { 512 if (_connection == null) { 513 getConnection(); 514 } 515 516 try { 517 if (Debug.verboseOn()) Debug.logVerbose("[SQLProcessor.execQuery]: " + sql, module); 518 executeQuery(sql); 519 520 boolean keepGoing = true; 523 524 while (keepGoing && _rs.next()) { 525 keepGoing = aListener.processNextRow(_rs); 526 } 527 528 if (_manualTX) { 529 _connection.commit(); 530 } 531 532 } catch (SQLException sqle) { 533 Debug.logWarning("[SQLProcessor.execQuery]: SQL Exception while executing the following:\n" + 534 sql + "\nError was:", module); 535 Debug.logWarning(sqle.getMessage(), module); 536 throw new GenericEntityException("SQL Exception while executing the following:" + _sql, sqle); 537 } finally { 538 close(); 539 } 540 } 541 542 549 public void setValue(String field) throws SQLException { 550 if (field != null) { 553 _ps.setString(_ind, field); 560 } else { 562 try { 565 _ps.setNull(_ind, Types.VARCHAR); 566 } catch (SQLException e) { 567 try { 568 _ps.setString(_ind, null); 569 } catch (SQLException e2) { 570 Debug.logError(e2, module); 571 throw e; 572 } 573 } 574 } 575 _ind++; 576 } 577 578 585 public void setValue(java.sql.Timestamp field) throws SQLException { 586 if (field != null) { 587 _ps.setTimestamp(_ind, field); 588 } else { 589 _ps.setNull(_ind, Types.TIMESTAMP); 590 } 591 _ind++; 592 } 593 594 601 public void setValue(java.sql.Time field) throws SQLException { 602 if (field != null) { 603 _ps.setTime(_ind, field); 604 } else { 605 _ps.setNull(_ind, Types.TIME); 606 } 607 _ind++; 608 } 609 610 617 public void setValue(java.sql.Date field) throws SQLException { 618 if (field != null) { 619 _ps.setDate(_ind, field); 620 } else { 621 _ps.setNull(_ind, Types.DATE); 622 } 623 _ind++; 624 } 625 626 633 public void setValue(Integer field) throws SQLException { 634 if (field != null) { 635 _ps.setInt(_ind, field.intValue()); 636 } else { 637 _ps.setNull(_ind, Types.NUMERIC); 638 } 639 _ind++; 640 } 641 642 649 public void setValue(Long field) throws SQLException { 650 if (field != null) { 651 _ps.setLong(_ind, field.longValue()); 652 } else { 653 _ps.setNull(_ind, Types.NUMERIC); 654 } 655 _ind++; 656 } 657 658 665 public void setValue(Float field) throws SQLException { 666 if (field != null) { 667 _ps.setFloat(_ind, field.floatValue()); 668 } else { 669 _ps.setNull(_ind, Types.NUMERIC); 670 } 671 _ind++; 672 } 673 674 681 public void setValue(Double field) throws SQLException { 682 if (field != null) { 683 _ps.setDouble(_ind, field.doubleValue()); 684 } else { 685 _ps.setNull(_ind, Types.NUMERIC); 686 } 687 _ind++; 688 } 689 690 697 public void setValue(BigDecimal field) throws SQLException { 698 if (field != null) { 699 _ps.setBigDecimal(_ind, field); 700 } else { 701 _ps.setNull(_ind, Types.NUMERIC); 702 } 703 _ind++; 704 } 705 706 713 public void setValue(Boolean field) throws SQLException { 714 if (field != null) { 715 _ps.setBoolean(_ind, field.booleanValue()); 716 } else { 717 _ps.setNull(_ind, Types.NULL); } 719 _ind++; 720 } 721 722 729 public void setValue(Object field) throws SQLException { 730 if (field != null) { 731 _ps.setObject(_ind, field, Types.JAVA_OBJECT); 732 } else { 733 _ps.setNull(_ind, Types.JAVA_OBJECT); 734 } 735 _ind++; 736 } 737 738 745 public void setValue(Blob field) throws SQLException { 746 if (field != null) { 747 _ps.setBlob(_ind, field); 748 } else { 749 _ps.setNull(_ind, Types.BLOB); 750 } 751 _ind++; 752 } 753 754 761 public void setValue(Clob field) throws SQLException { 762 if (field != null) { 763 _ps.setClob(_ind, field); 764 } else { 765 _ps.setNull(_ind, Types.CLOB); 766 } 767 _ind++; 768 } 769 770 778 public void setBinaryStream(Object field) throws SQLException { 779 if (field != null) { 780 try { 781 ByteArrayOutputStream os = new ByteArrayOutputStream (); 782 ObjectOutputStream oos = new ObjectOutputStream (os); 783 oos.writeObject(field); 784 oos.close(); 785 786 byte[] buf = os.toByteArray(); 787 os.close(); 788 ByteArrayInputStream is = new ByteArrayInputStream (buf); 789 _ps.setBinaryStream(_ind, is, buf.length); 790 is.close(); 791 } catch (IOException ex) { 792 throw new SQLException(ex.getMessage()); 793 } 794 } else { 795 _ps.setNull(_ind, Types.BINARY); 796 } 797 798 _ind++; 799 } 800 801 protected void finalize() throws Throwable { 802 try { 803 this.close(); 804 } catch (Exception e) { 805 Debug.logError(e, "Error closing the result, connection, etc in finalize SQLProcessor", module); 806 } 807 super.finalize(); 808 } 809 810 protected void testConnection(Connection con) throws GenericEntityException { 811 if (SQLProcessor.ENABLE_TEST) { 812 if (SQLProcessor.CONNECTION_TEST_LIST.contains(con.toString())) { 813 throw new GenericEntityException("Connection the exact same as index " + SQLProcessor.CONNECTION_TEST_LIST.indexOf(con.toString())); 814 } 815 SQLProcessor.CONNECTION_TEST_LIST.add(con.toString()); 816 if (SQLProcessor.CONNECTION_TEST_LIST.size() > SQLProcessor.MAX_CONNECTIONS) { 817 SQLProcessor.CONNECTION_TEST_LIST.remove(0); 818 } 819 } 820 } 821 822 protected void setFetchSize(Statement stmt, int fetchSize) throws SQLException { 823 if (_connection instanceof CursorConnection) return; 825 826 if (fetchSize < 0) { 828 DatasourceInfo ds = EntityConfigUtil.getDatasourceInfo(helperName); 829 if (ds != null) { 830 fetchSize = ds.resultFetchSize; 831 } else { 832 Debug.logWarning("DatasourceInfo is null, not setting fetch size!", module); 833 } 834 } 835 836 if (fetchSize > -1) { 838 stmt.setFetchSize(fetchSize); 839 } 840 } 841 } 842 | Popular Tags |