1 16 package com.ibatis.sqlmap.engine.impl; 17 18 import com.ibatis.common.beans.Probe; 19 import com.ibatis.common.beans.ProbeFactory; 20 import com.ibatis.common.jdbc.exception.NestedSQLException; 21 import com.ibatis.common.util.PaginatedList; 22 import com.ibatis.common.util.ThrottledPool; 23 import com.ibatis.sqlmap.client.SqlMapException; 24 import com.ibatis.sqlmap.client.event.RowHandler; 25 import com.ibatis.sqlmap.engine.cache.CacheKey; 26 import com.ibatis.sqlmap.engine.cache.CacheModel; 27 import com.ibatis.sqlmap.engine.exchange.DataExchangeFactory; 28 import com.ibatis.sqlmap.engine.execution.SqlExecutor; 29 import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMap; 30 import com.ibatis.sqlmap.engine.mapping.result.ResultMap; 31 import com.ibatis.sqlmap.engine.mapping.statement.InsertStatement; 32 import com.ibatis.sqlmap.engine.mapping.statement.MappedStatement; 33 import com.ibatis.sqlmap.engine.mapping.statement.PaginatedDataList; 34 import com.ibatis.sqlmap.engine.mapping.statement.SelectKeyStatement; 35 import com.ibatis.sqlmap.engine.scope.RequestScope; 36 import com.ibatis.sqlmap.engine.scope.SessionScope; 37 import com.ibatis.sqlmap.engine.transaction.Transaction; 38 import com.ibatis.sqlmap.engine.transaction.TransactionException; 39 import com.ibatis.sqlmap.engine.transaction.TransactionManager; 40 import com.ibatis.sqlmap.engine.transaction.TransactionState; 41 import com.ibatis.sqlmap.engine.transaction.user.UserProvidedTransaction; 42 import com.ibatis.sqlmap.engine.type.TypeHandlerFactory; 43 44 import javax.sql.DataSource ; 45 import java.sql.Connection ; 46 import java.sql.SQLException ; 47 import java.util.HashMap ; 48 import java.util.Iterator ; 49 import java.util.List ; 50 import java.util.Map ; 51 52 55 public class SqlMapExecutorDelegate { 56 57 private static final Probe PROBE = ProbeFactory.getProbe(); 58 59 62 public static final int DEFAULT_MAX_REQUESTS = 512; 63 66 public static final int DEFAULT_MAX_SESSIONS = 128; 67 70 public static final int DEFAULT_MAX_TRANSACTIONS = 32; 71 72 private boolean lazyLoadingEnabled; 73 private boolean cacheModelsEnabled; 74 private boolean enhancementEnabled; 75 76 private int maxRequests = DEFAULT_MAX_REQUESTS; 77 private int maxSessions = DEFAULT_MAX_SESSIONS; 78 private int maxTransactions = DEFAULT_MAX_TRANSACTIONS; 79 80 private TransactionManager txManager; 81 82 private HashMap mappedStatements; 83 private HashMap cacheModels; 84 private HashMap resultMaps; 85 private HashMap parameterMaps; 86 87 private ThrottledPool requestPool; 88 private ThrottledPool sessionPool; 89 90 private SqlExecutor sqlExecutor; 91 private TypeHandlerFactory typeHandlerFactory; 92 private DataExchangeFactory dataExchangeFactory; 93 94 97 public SqlMapExecutorDelegate() { 98 mappedStatements = new HashMap (); 99 cacheModels = new HashMap (); 100 resultMaps = new HashMap (); 101 parameterMaps = new HashMap (); 102 103 requestPool = new ThrottledPool(RequestScope.class, DEFAULT_MAX_REQUESTS); 104 sessionPool = new ThrottledPool(SessionScope.class, DEFAULT_MAX_SESSIONS); 105 106 sqlExecutor = new SqlExecutor(); 107 typeHandlerFactory = new TypeHandlerFactory(); 108 dataExchangeFactory = new DataExchangeFactory(typeHandlerFactory); 109 } 110 111 116 public DataExchangeFactory getDataExchangeFactory() { 117 return dataExchangeFactory; 118 } 119 120 125 public TypeHandlerFactory getTypeHandlerFactory() { 126 return typeHandlerFactory; 127 } 128 129 134 public boolean isLazyLoadingEnabled() { 135 return lazyLoadingEnabled; 136 } 137 138 143 public void setLazyLoadingEnabled(boolean lazyLoadingEnabled) { 144 this.lazyLoadingEnabled = lazyLoadingEnabled; 145 } 146 147 152 public boolean isCacheModelsEnabled() { 153 return cacheModelsEnabled; 154 } 155 156 161 public void setCacheModelsEnabled(boolean cacheModelsEnabled) { 162 this.cacheModelsEnabled = cacheModelsEnabled; 163 } 164 165 170 public boolean isEnhancementEnabled() { 171 return enhancementEnabled; 172 } 173 174 179 public void setEnhancementEnabled(boolean enhancementEnabled) { 180 this.enhancementEnabled = enhancementEnabled; 181 } 182 183 188 public int getMaxRequests() { 189 return maxRequests; 190 } 191 192 197 public void setMaxRequests(int maxRequests) { 198 this.maxRequests = maxRequests; 199 requestPool = new ThrottledPool(RequestScope.class, maxRequests); 200 } 201 202 207 public int getMaxSessions() { 208 return maxSessions; 209 } 210 211 216 public void setMaxSessions(int maxSessions) { 217 this.maxSessions = maxSessions; 218 this.sessionPool = new ThrottledPool(SessionScope.class, maxSessions); 219 } 220 221 226 public int getMaxTransactions() { 227 return maxTransactions; 228 } 229 230 235 public void setMaxTransactions(int maxTransactions) { 236 this.maxTransactions = maxTransactions; 237 } 238 239 244 public TransactionManager getTxManager() { 245 return txManager; 246 } 247 248 253 public void setTxManager(TransactionManager txManager) { 254 this.txManager = txManager; 255 } 256 257 262 public void addMappedStatement(MappedStatement ms) { 263 if (mappedStatements.containsKey(ms.getId())) { 264 throw new SqlMapException("There is already a statement named " + ms.getId() + " in this SqlMap."); 265 } 266 ms.setBaseCacheKey(hashCode()); 267 mappedStatements.put(ms.getId(), ms); 268 } 269 270 275 public Iterator getMappedStatementNames() { 276 return mappedStatements.keySet().iterator(); 277 } 278 279 285 public MappedStatement getMappedStatement(String id) { 286 MappedStatement ms = (MappedStatement) mappedStatements.get(id); 287 if (ms == null) { 288 throw new SqlMapException("There is no statement named " + id + " in this SqlMap."); 289 } 290 return ms; 291 } 292 293 298 public void addCacheModel(CacheModel model) { 299 cacheModels.put(model.getId(), model); 300 } 301 302 307 public Iterator getCacheModelNames() { 308 return cacheModels.keySet().iterator(); 309 } 310 311 317 public CacheModel getCacheModel(String id) { 318 CacheModel model = (CacheModel) cacheModels.get(id); 319 if (model == null) { 320 throw new SqlMapException("There is no cache model named " + id + " in this SqlMap."); 321 } 322 return model; 323 } 324 325 330 public void addResultMap(ResultMap map) { 331 resultMaps.put(map.getId(), map); 332 } 333 334 339 public Iterator getResultMapNames() { 340 return resultMaps.keySet().iterator(); 341 } 342 343 349 public ResultMap getResultMap(String id) { 350 ResultMap map = (ResultMap) resultMaps.get(id); 351 if (map == null) { 352 throw new SqlMapException("There is no result map named " + id + " in this SqlMap."); 353 } 354 return map; 355 } 356 357 362 public void addParameterMap(ParameterMap map) { 363 parameterMaps.put(map.getId(), map); 364 } 365 366 371 public Iterator getParameterMapNames() { 372 return parameterMaps.keySet().iterator(); 373 } 374 375 381 public ParameterMap getParameterMap(String id) { 382 ParameterMap map = (ParameterMap) parameterMaps.get(id); 383 if (map == null) { 384 throw new SqlMapException("There is no parameter map named " + id + " in this SqlMap."); 385 } 386 return map; 387 } 388 389 392 public void flushDataCache() { 393 Iterator models = cacheModels.values().iterator(); 394 while (models.hasNext()) { 395 ((CacheModel) models.next()).flush(); 396 } 397 } 398 399 404 public void flushDataCache(String id) { 405 CacheModel model = getCacheModel(id); 406 if (model != null) { 407 model.flush(); 408 } 409 } 410 411 421 public Object insert(SessionScope session, String id, Object param) throws SQLException { 422 Object generatedKey = null; 423 424 MappedStatement ms = getMappedStatement(id); 425 Transaction trans = getTransaction(session); 426 boolean autoStart = trans == null; 427 428 try { 429 trans = autoStartTransaction(session, autoStart, trans); 430 431 SelectKeyStatement selectKeyStatement = null; 432 if (ms instanceof InsertStatement) { 433 selectKeyStatement = ((InsertStatement) ms).getSelectKeyStatement(); 434 } 435 436 if (selectKeyStatement != null && !selectKeyStatement.isAfter()) { 437 generatedKey = executeSelectKey(session, trans, ms, param); 438 } 439 440 RequestScope request = popRequest(session, ms); 441 try { 442 ms.executeUpdate(request, trans, param); 443 } finally { 444 pushRequest(request); 445 } 446 447 if (selectKeyStatement != null && selectKeyStatement.isAfter()) { 448 generatedKey = executeSelectKey(session, trans, ms, param); 449 } 450 451 autoCommitTransaction(session, autoStart); 452 } finally { 453 autoEndTransaction(session, autoStart); 454 } 455 456 return generatedKey; 457 } 458 459 private Object executeSelectKey(SessionScope session, Transaction trans, MappedStatement ms, Object param) throws SQLException { 460 Object generatedKey = null; 461 RequestScope request; 462 InsertStatement insert = (InsertStatement) ms; 463 SelectKeyStatement selectKeyStatement = insert.getSelectKeyStatement(); 464 if (selectKeyStatement != null) { 465 request = popRequest(session, selectKeyStatement); 466 try { 467 generatedKey = selectKeyStatement.executeQueryForObject(request, trans, param, null); 468 String keyProp = selectKeyStatement.getKeyProperty(); 469 if (keyProp != null) { 470 PROBE.setObject(param, keyProp, generatedKey); 471 } 472 } finally { 473 pushRequest(request); 474 } 475 } 476 return generatedKey; 477 } 478 479 488 public int update(SessionScope session, String id, Object param) throws SQLException { 489 int rows = 0; 490 491 MappedStatement ms = getMappedStatement(id); 492 Transaction trans = getTransaction(session); 493 boolean autoStart = trans == null; 494 495 try { 496 trans = autoStartTransaction(session, autoStart, trans); 497 498 RequestScope request = popRequest(session, ms); 499 try { 500 rows = ms.executeUpdate(request, trans, param); 501 } finally { 502 pushRequest(request); 503 } 504 505 autoCommitTransaction(session, autoStart); 506 } finally { 507 autoEndTransaction(session, autoStart); 508 } 509 510 return rows; 511 } 512 513 522 public int delete(SessionScope session, String id, Object param) throws SQLException { 523 return update(session, id, param); 524 } 525 526 535 public Object queryForObject(SessionScope session, String id, Object paramObject) throws SQLException { 536 return queryForObject(session, id, paramObject, null); 537 } 538 539 549 public Object queryForObject(SessionScope session, String id, Object paramObject, Object resultObject) throws SQLException { 550 Object object = null; 551 552 MappedStatement ms = getMappedStatement(id); 553 Transaction trans = getTransaction(session); 554 boolean autoStart = trans == null; 555 556 try { 557 trans = autoStartTransaction(session, autoStart, trans); 558 559 RequestScope request = popRequest(session, ms); 560 try { 561 object = ms.executeQueryForObject(request, trans, paramObject, resultObject); 562 } finally { 563 pushRequest(request); 564 } 565 566 autoCommitTransaction(session, autoStart); 567 } finally { 568 autoEndTransaction(session, autoStart); 569 } 570 571 return object; 572 } 573 574 583 public List queryForList(SessionScope session, String id, Object paramObject) throws SQLException { 584 return queryForList(session, id, paramObject, SqlExecutor.NO_SKIPPED_RESULTS, SqlExecutor.NO_MAXIMUM_RESULTS); 585 } 586 587 598 public List queryForList(SessionScope session, String id, Object paramObject, int skip, int max) throws SQLException { 599 List list = null; 600 601 MappedStatement ms = getMappedStatement(id); 602 Transaction trans = getTransaction(session); 603 boolean autoStart = trans == null; 604 605 try { 606 trans = autoStartTransaction(session, autoStart, trans); 607 608 RequestScope request = popRequest(session, ms); 609 try { 610 list = ms.executeQueryForList(request, trans, paramObject, skip, max); 611 } finally { 612 pushRequest(request); 613 } 614 615 autoCommitTransaction(session, autoStart); 616 } finally { 617 autoEndTransaction(session, autoStart); 618 } 619 620 return list; 621 } 622 623 633 public void queryWithRowHandler(SessionScope session, String id, Object paramObject, RowHandler rowHandler) throws SQLException { 634 635 MappedStatement ms = getMappedStatement(id); 636 Transaction trans = getTransaction(session); 637 boolean autoStart = trans == null; 638 639 try { 640 trans = autoStartTransaction(session, autoStart, trans); 641 642 RequestScope request = popRequest(session, ms); 643 try { 644 ms.executeQueryWithRowHandler(request, trans, paramObject, rowHandler); 645 } finally { 646 pushRequest(request); 647 } 648 649 autoCommitTransaction(session, autoStart); 650 } finally { 651 autoEndTransaction(session, autoStart); 652 } 653 654 } 655 656 666 public PaginatedList queryForPaginatedList(SessionScope session, String id, Object paramObject, int pageSize) throws SQLException { 667 return new PaginatedDataList(session.getSqlMapExecutor(), id, paramObject, pageSize); 668 } 669 670 681 public Map queryForMap(SessionScope session, String id, Object paramObject, String keyProp) throws SQLException { 682 return queryForMap(session, id, paramObject, keyProp, null); 683 } 684 685 697 public Map queryForMap(SessionScope session, String id, Object paramObject, String keyProp, String valueProp) throws SQLException { 698 Map map = new HashMap (); 699 700 List list = queryForList(session, id, paramObject); 701 702 for (int i = 0, n = list.size(); i < n; i++) { 703 Object object = list.get(i); 704 Object key = PROBE.getObject(object, keyProp); 705 Object value = null; 706 if (valueProp == null) { 707 value = object; 708 } else { 709 value = PROBE.getObject(object, valueProp); 710 } 711 map.put(key, value); 712 } 713 714 return map; 715 } 716 717 724 public void startTransaction(SessionScope session) throws SQLException { 725 try { 726 txManager.begin(session); 727 } catch (TransactionException e) { 728 throw new NestedSQLException("Could not start transaction. Cause: " + e, e); 729 } 730 } 731 732 738 public void startTransaction(SessionScope session, int transactionIsolation) throws SQLException { 739 try { 740 txManager.begin(session, transactionIsolation); 741 } catch (TransactionException e) { 742 throw new NestedSQLException("Could not start transaction. Cause: " + e, e); 743 } 744 } 745 746 752 public void commitTransaction(SessionScope session) throws SQLException { 753 try { 754 if (session.isInBatch()) { 756 executeBatch(session); 757 } 758 sqlExecutor.cleanup(session); 759 txManager.commit(session); 760 } catch (TransactionException e) { 761 throw new NestedSQLException("Could not commit transaction. Cause: " + e, e); 762 } 763 } 764 765 771 public void endTransaction(SessionScope session) throws SQLException { 772 try { 773 try { 774 sqlExecutor.cleanup(session); 775 } finally { 776 txManager.end(session); 777 } 778 } catch (TransactionException e) { 779 throw new NestedSQLException("Error while ending transaction. Cause: " + e, e); 780 } 781 } 782 783 788 public void startBatch(SessionScope session) { 789 session.setInBatch(true); 790 } 791 792 799 public int executeBatch(SessionScope session) throws SQLException { 800 session.setInBatch(false); 801 return sqlExecutor.executeBatch(session); 802 } 803 804 810 public void setUserProvidedTransaction(SessionScope session, Connection userConnection) { 811 if (session.getTransactionState() == TransactionState.STATE_USER_PROVIDED) { 812 session.recallTransactionState(); 813 } 814 if (userConnection != null) { 815 Connection conn = userConnection; 816 session.saveTransactionState(); 817 session.setTransaction(new UserProvidedTransaction(conn)); 818 session.setTransactionState(TransactionState.STATE_USER_PROVIDED); 819 } else { 820 session.setTransaction(null); 821 pushSession(session); 822 } 823 } 824 829 public DataSource getDataSource() { 830 DataSource ds = null; 831 if (txManager != null) { 832 ds = txManager.getDataSource(); 833 } 834 return ds; 835 } 836 837 842 public SqlExecutor getSqlExecutor() { 843 return sqlExecutor; 844 } 845 846 852 public Transaction getTransaction(SessionScope session) { 853 return session.getTransaction(); 854 } 855 856 858 private void autoEndTransaction(SessionScope session, boolean autoStart) throws SQLException { 859 if (autoStart) { 860 session.getSqlMapTxMgr().endTransaction(); 861 } 862 } 863 864 private void autoCommitTransaction(SessionScope session, boolean autoStart) throws SQLException { 865 if (autoStart) { 866 session.getSqlMapTxMgr().commitTransaction(); 867 } 868 } 869 870 private Transaction autoStartTransaction(SessionScope session, boolean autoStart, Transaction trans) throws SQLException { 871 Transaction transaction = trans; 872 if (autoStart) { 873 session.getSqlMapTxMgr().startTransaction(); 874 transaction = getTransaction(session); 875 } 876 return transaction; 877 } 878 879 public boolean equals(Object obj) { 880 return this == obj; 881 } 882 883 public int hashCode() { 884 CacheKey key = new CacheKey(); 885 if (txManager != null) { 886 key.update(txManager); 887 if (txManager.getDataSource() != null) { 888 key.update(txManager.getDataSource()); 889 } 890 } 891 key.update(System.identityHashCode(this)); 892 return key.hashCode(); 893 } 894 895 protected RequestScope popRequest(SessionScope session, MappedStatement mappedStatement) { 896 RequestScope request = (RequestScope) requestPool.pop(); 897 session.incrementRequestStackDepth(); 898 request.setSession(session); 899 mappedStatement.initRequest(request); 900 return request; 901 } 902 903 protected void pushRequest(RequestScope request) { 904 request.getSession().decrementRequestStackDepth(); 905 request.reset(); 906 requestPool.push(request); 907 } 908 909 protected SessionScope popSession() { 910 return (SessionScope) sessionPool.pop(); 911 } 912 913 protected void pushSession(SessionScope session) { 914 session.reset(); 915 sessionPool.push(session); 916 } 917 918 } 919 920 | Popular Tags |