Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/ibatis/sqlmap/engine/impl/SqlMapExecutorDelegate.java


1   /*
2    *  Copyright 2004 Clinton Begin
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
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  /**
53   * The workhorse that really runs the SQL
54   */
55  public class SqlMapExecutorDelegate {
56  
57    private static final Probe PROBE = ProbeFactory.getProbe();
58  
59    /**
60     * The default maximum number of requests
61     */
62    public static final int DEFAULT_MAX_REQUESTS = 512;
63    /**
64     * The default maximum number of sessions
65     */
66    public static final int DEFAULT_MAX_SESSIONS = 128;
67    /**
68     * The default maximum number of transactions
69     */
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    /**
95     * Default constructor
96     */
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   /**
112    * Getter for the DataExchangeFactory
113    *
114    * @return - the DataExchangeFactory
115    */
116   public DataExchangeFactory getDataExchangeFactory() {
117     return dataExchangeFactory;
118   }
119 
120   /**
121    * Getter for the TypeHandlerFactory
122    *
123    * @return - the TypeHandlerFactory
124    */
125   public TypeHandlerFactory getTypeHandlerFactory() {
126     return typeHandlerFactory;
127   }
128 
129   /**
130    * Getter for the status of lazy loading
131    *
132    * @return - the status
133    */
134   public boolean isLazyLoadingEnabled() {
135     return lazyLoadingEnabled;
136   }
137 
138   /**
139    * Turn on or off lazy loading
140    *
141    * @param lazyLoadingEnabled - the new state of caching
142    */
143   public void setLazyLoadingEnabled(boolean lazyLoadingEnabled) {
144     this.lazyLoadingEnabled = lazyLoadingEnabled;
145   }
146 
147   /**
148    * Getter for the status of caching
149    *
150    * @return - the status
151    */
152   public boolean isCacheModelsEnabled() {
153     return cacheModelsEnabled;
154   }
155 
156   /**
157    * Turn on or off caching
158    *
159    * @param cacheModelsEnabled - the new state of caching
160    */
161   public void setCacheModelsEnabled(boolean cacheModelsEnabled) {
162     this.cacheModelsEnabled = cacheModelsEnabled;
163   }
164 
165   /**
166    * Getter for the status of CGLib enhancements
167    *
168    * @return - the status
169    */
170   public boolean isEnhancementEnabled() {
171     return enhancementEnabled;
172   }
173 
174   /**
175    * Turn on or off CGLib enhancements
176    *
177    * @param enhancementEnabled - the new state
178    */
179   public void setEnhancementEnabled(boolean enhancementEnabled) {
180     this.enhancementEnabled = enhancementEnabled;
181   }
182 
183   /**
184    * Getter for the maximum number of requests
185    *
186    * @return - the maximum number of requests
187    */
188   public int getMaxRequests() {
189     return maxRequests;
190   }
191 
192   /**
193    * Setter for the maximum number of requests
194    *
195    * @param maxRequests - the maximum number of requests
196    */
197   public void setMaxRequests(int maxRequests) {
198     this.maxRequests = maxRequests;
199     requestPool = new ThrottledPool(RequestScope.class, maxRequests);
200   }
201 
202   /**
203    * Getter for the maximum number of sessions
204    *
205    * @return - the maximum number of sessions
206    */
207   public int getMaxSessions() {
208     return maxSessions;
209   }
210 
211   /**
212    * Setter for the maximum number of sessions
213    *
214    * @param maxSessions - the maximum number of sessions
215    */
216   public void setMaxSessions(int maxSessions) {
217     this.maxSessions = maxSessions;
218     this.sessionPool = new ThrottledPool(SessionScope.class, maxSessions);
219   }
220 
221   /**
222    * Getter for the the maximum number of transactions
223    *
224    * @return - the maximum number of transactions
225    */
226   public int getMaxTransactions() {
227     return maxTransactions;
228   }
229 
230   /**
231    * Setter for the maximum number of transactions
232    *
233    * @param maxTransactions - the maximum number of transactions
234    */
235   public void setMaxTransactions(int maxTransactions) {
236     this.maxTransactions = maxTransactions;
237   }
238 
239   /**
240    * Getter for the transaction manager
241    *
242    * @return - the transaction manager
243    */
244   public TransactionManager getTxManager() {
245     return txManager;
246   }
247 
248   /**
249    * Setter for the transaction manager
250    *
251    * @param txManager - the transaction manager
252    */
253   public void setTxManager(TransactionManager txManager) {
254     this.txManager = txManager;
255   }
256 
257   /**
258    * Add a mapped statement
259    *
260    * @param ms - the mapped statement to add
261    */
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   /**
271    * Get an iterator of the mapped statements
272    *
273    * @return - the iterator
274    */
275   public Iterator getMappedStatementNames() {
276     return mappedStatements.keySet().iterator();
277   }
278 
279   /**
280    * Get a mappedstatement by its ID
281    *
282    * @param id - the statement ID
283    * @return - the mapped statement
284    */
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   /**
294    * Add a cache model
295    *
296    * @param model - the model to add
297    */
298   public void addCacheModel(CacheModel model) {
299     cacheModels.put(model.getId(), model);
300   }
301 
302   /**
303    * Get an iterator of the cache models
304    *
305    * @return - the cache models
306    */
307   public Iterator getCacheModelNames() {
308     return cacheModels.keySet().iterator();
309   }
310 
311   /**
312    * Get a cache model by ID
313    *
314    * @param id - the ID
315    * @return - the cache model
316    */
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   /**
326    * Add a result map
327    *
328    * @param map - the result map to add
329    */
330   public void addResultMap(ResultMap map) {
331     resultMaps.put(map.getId(), map);
332   }
333 
334   /**
335    * Get an iterator of the result maps
336    *
337    * @return - the result maps
338    */
339   public Iterator getResultMapNames() {
340     return resultMaps.keySet().iterator();
341   }
342 
343   /**
344    * Get a result map by ID
345    *
346    * @param id - the ID
347    * @return - the result map
348    */
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   /**
358    * Add a parameter map
359    *
360    * @param map - the map to add
361    */
362   public void addParameterMap(ParameterMap map) {
363     parameterMaps.put(map.getId(), map);
364   }
365 
366   /**
367    * Get an iterator of all of the parameter maps
368    *
369    * @return - the parameter maps
370    */
371   public Iterator getParameterMapNames() {
372     return parameterMaps.keySet().iterator();
373   }
374 
375   /**
376    * Get a parameter map by ID
377    *
378    * @param id - the ID
379    * @return - the parameter map
380    */
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   /**
390    * Flush all of the data caches
391    */
392   public void flushDataCache() {
393     Iterator models = cacheModels.values().iterator();
394     while (models.hasNext()) {
395       ((CacheModel) models.next()).flush();
396     }
397   }
398 
399   /**
400    * Flush a single cache by ID
401    *
402    * @param id - the ID
403    */
404   public void flushDataCache(String id) {
405     CacheModel model = getCacheModel(id);
406     if (model != null) {
407       model.flush();
408     }
409   }
410 
411   //-- Basic Methods
412   /**
413    * Call an insert statement by ID
414    *
415    * @param session - the session
416    * @param id      - the statement ID
417    * @param param   - the parameter object
418    * @return - the generated key (or null)
419    * @throws SQLException - if the insert fails
420    */
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   /**
480    * Execute an update statement
481    *
482    * @param session - the session scope
483    * @param id      - the statement ID
484    * @param param   - the parameter object
485    * @return - the number of rows updated
486    * @throws SQLException - if the update fails
487    */
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   /**
514    * Execute a delete statement
515    *
516    * @param session - the session scope
517    * @param id      - the statement ID
518    * @param param   - the parameter object
519    * @return - the number of rows deleted
520    * @throws SQLException - if the delete fails
521    */
522   public int delete(SessionScope session, String id, Object param) throws SQLException {
523     return update(session, id, param);
524   }
525 
526   /**
527    * Execute a select for a single object
528    *
529    * @param session     - the session scope
530    * @param id          - the statement ID
531    * @param paramObject - the parameter object
532    * @return - the result of the query
533    * @throws SQLException - if the query fails
534    */
535   public Object queryForObject(SessionScope session, String id, Object paramObject) throws SQLException {
536     return queryForObject(session, id, paramObject, null);
537   }
538 
539   /**
540    * Execute a select for a single object
541    *
542    * @param session      - the session scope
543    * @param id           - the statement ID
544    * @param paramObject  - the parameter object
545    * @param resultObject - the result object (if not supplied or null, a new object will be created)
546    * @return - the result of the query
547    * @throws SQLException - if the query fails
548    */
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   /**
575    * Execute a query for a list
576    *
577    * @param session     - the session scope
578    * @param id          - the statement ID
579    * @param paramObject - the parameter object
580    * @return - the data list
581    * @throws SQLException - if the query fails
582    */
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   /**
588    * Execute a query for a list
589    *
590    * @param session     - the session scope
591    * @param id          - the statement ID
592    * @param paramObject - the parameter object
593    * @param skip        - the number of rows to skip
594    * @param max         - the maximum number of rows to return
595    * @return - the data list
596    * @throws SQLException - if the query fails
597    */
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   /**
624    * Execute a query with a row handler.
625    * The row handler is called once per row in the query results.
626    *
627    * @param session     - the session scope
628    * @param id          - the statement ID
629    * @param paramObject - the parameter object
630    * @param rowHandler  - the row handler
631    * @throws SQLException - if the query fails
632    */
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   /**
657    * Execute a query and return a paginated list
658    *
659    * @param session     - the session scope
660    * @param id          - the statement ID
661    * @param paramObject - the parameter object
662    * @param pageSize    - the page size
663    * @return - the data list
664    * @throws SQLException - if the query fails
665    */
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   /**
671    * Execute a query for a map.
672    * The map has the table key as the key, and the results as the map data
673    *
674    * @param session     - the session scope
675    * @param id          - the statement ID
676    * @param paramObject - the parameter object
677    * @param keyProp     - the key property (from the results for the map)
678    * @return - the Map
679    * @throws SQLException - if the query fails
680    */
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   /**
686    * Execute a query for a map.
687    * The map has the table key as the key, and a property from the results as the map data
688    *
689    * @param session     - the session scope
690    * @param id          - the statement ID
691    * @param paramObject - the parameter object
692    * @param keyProp     - the property for the map key
693    * @param valueProp   - the property for the map data
694    * @return - the Map
695    * @throws SQLException - if the query fails
696    */
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   // -- Transaction Control Methods
718   /**
719    * Start a transaction on the session
720    *
721    * @param session - the session
722    * @throws SQLException - if the transaction could not be started
723    */
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   /**
733    * Start a transaction on the session with the specified isolation level.
734    *
735    * @param session - the session
736    * @throws SQLException - if the transaction could not be started
737    */
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   /**
747    * Commit the transaction on a session
748    *
749    * @param session - the session
750    * @throws SQLException - if the transaction could not be committed
751    */
752   public void commitTransaction(SessionScope session) throws SQLException {
753     try {
754       // Auto batch execution
755       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   /**
766    * End the transaction on a session
767    *
768    * @param session - the session
769    * @throws SQLException - if the transaction could not be ended
770    */
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   /**
784    * Start a batch for a session
785    *
786    * @param session - the session
787    */
788   public void startBatch(SessionScope session) {
789     session.setInBatch(true);
790   }
791 
792   /**
793    * Execute a batch for a session
794    *
795    * @param session - the session
796    * @return - the number of rows impacted by the batch
797    * @throws SQLException - if the batch fails
798    */
799   public int executeBatch(SessionScope session) throws SQLException {
800     session.setInBatch(false);
801     return sqlExecutor.executeBatch(session);
802   }
803 
804   /**
805    * Use a user-provided transaction for a session
806    *
807    * @param session        - the session scope
808    * @param userConnection - the user supplied connection
809    */
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   /**
825    * Get the DataSource for the session
826    *
827    * @return - the DataSource
828    */
829   public DataSource getDataSource() {
830     DataSource ds = null;
831     if (txManager != null) {
832       ds = txManager.getDataSource();
833     }
834     return ds;
835   }
836 
837   /**
838    * Getter for the SqlExecutor
839    *
840    * @return the SqlExecutor
841    */
842   public SqlExecutor getSqlExecutor() {
843     return sqlExecutor;
844   }
845 
846   /**
847    * Get a transaction for the session
848    *
849    * @param session - the session
850    * @return - the transaction
851    */
852   public Transaction getTransaction(SessionScope session) {
853     return session.getTransaction();
854   }
855 
856   // -- Private Methods
857 
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