View Javadoc
1   /*
2    * Copyright 2004-2022 the original author or authors.
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    *    https://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.scope;
17  
18  import com.ibatis.sqlmap.client.SqlMapClient;
19  import com.ibatis.sqlmap.client.SqlMapException;
20  import com.ibatis.sqlmap.client.SqlMapExecutor;
21  import com.ibatis.sqlmap.client.SqlMapTransactionManager;
22  import com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate;
23  import com.ibatis.sqlmap.engine.transaction.Transaction;
24  import com.ibatis.sqlmap.engine.transaction.TransactionState;
25  
26  import java.sql.PreparedStatement;
27  import java.sql.SQLException;
28  import java.util.HashMap;
29  import java.util.Iterator;
30  import java.util.Map;
31  
32  /**
33   * A Session based implementation of the Scope interface.
34   */
35  public class SessionScope {
36  
37    /** The next id. */
38    private static long nextId;
39  
40    /** The id. */
41    private long id;
42  
43    /** The sql map client. */
44    // Used by Any
45    private SqlMapClient sqlMapClient;
46  
47    /** The sql map executor. */
48    private SqlMapExecutor sqlMapExecutor;
49  
50    /** The sql map tx mgr. */
51    private SqlMapTransactionManager sqlMapTxMgr;
52  
53    /** The request stack depth. */
54    private int requestStackDepth;
55  
56    /** The transaction. */
57    // Used by TransactionManager
58    private Transaction transaction;
59  
60    /** The transaction state. */
61    private TransactionState transactionState;
62  
63    /** The saved transaction state. */
64    // Used by SqlMapExecutorDelegate.setUserProvidedTransaction()
65    private TransactionState savedTransactionState;
66  
67    /** The in batch. */
68    // Used by StandardSqlMapClient and GeneralStatement
69    private boolean inBatch;
70  
71    /** The batch. */
72    // Used by SqlExecutor
73    private Object batch;
74  
75    /** The commit required. */
76    private boolean commitRequired;
77  
78    /** The prepared statements. */
79    private Map preparedStatements;
80  
81    /**
82     * Default constructor.
83     */
84    public SessionScope() {
85      this.preparedStatements = new HashMap();
86      this.inBatch = false;
87      this.requestStackDepth = 0;
88      this.id = getNextId();
89    }
90  
91    /**
92     * Get the SqlMapClient for the session.
93     *
94     * @return - the SqlMapClient
95     */
96    public SqlMapClient getSqlMapClient() {
97      return sqlMapClient;
98    }
99  
100   /**
101    * Set the SqlMapClient for the session.
102    *
103    * @param sqlMapClient
104    *          - the SqlMapClient
105    */
106   public void setSqlMapClient(SqlMapClient sqlMapClient) {
107     this.sqlMapClient = sqlMapClient;
108   }
109 
110   /**
111    * Get the SQL executor for the session.
112    *
113    * @return - the SQL executor
114    */
115   public SqlMapExecutor getSqlMapExecutor() {
116     return sqlMapExecutor;
117   }
118 
119   /**
120    * Get the SQL executor for the session.
121    *
122    * @param sqlMapExecutor
123    *          - the SQL executor
124    */
125   public void setSqlMapExecutor(SqlMapExecutor sqlMapExecutor) {
126     this.sqlMapExecutor = sqlMapExecutor;
127   }
128 
129   /**
130    * Get the transaction manager.
131    *
132    * @return - the transaction manager
133    */
134   public SqlMapTransactionManager getSqlMapTxMgr() {
135     return sqlMapTxMgr;
136   }
137 
138   /**
139    * Set the transaction manager.
140    *
141    * @param sqlMapTxMgr
142    *          - the transaction manager
143    */
144   public void setSqlMapTxMgr(SqlMapTransactionManager sqlMapTxMgr) {
145     this.sqlMapTxMgr = sqlMapTxMgr;
146   }
147 
148   /**
149    * Tells us if we are in batch mode or not.
150    *
151    * @return - true if we are working with a batch
152    */
153   public boolean isInBatch() {
154     return inBatch;
155   }
156 
157   /**
158    * Turn batch mode on or off.
159    *
160    * @param inBatch
161    *          - the switch
162    */
163   public void setInBatch(boolean inBatch) {
164     this.inBatch = inBatch;
165   }
166 
167   /**
168    * Getter for the session transaction.
169    *
170    * @return - the transaction
171    */
172   public Transaction getTransaction() {
173     return transaction;
174   }
175 
176   /**
177    * Setter for the session transaction.
178    *
179    * @param transaction
180    *          - the transaction
181    */
182   public void setTransaction(Transaction transaction) {
183     this.transaction = transaction;
184   }
185 
186   /**
187    * Getter for the transaction state of the session.
188    *
189    * @return - the state
190    */
191   public TransactionState getTransactionState() {
192     return transactionState;
193   }
194 
195   /**
196    * Setter for the transaction state of the session.
197    *
198    * @param transactionState
199    *          - the new transaction state
200    */
201   public void setTransactionState(TransactionState transactionState) {
202     this.transactionState = transactionState;
203   }
204 
205   /**
206    * Getter for the batch of the session.
207    *
208    * @return - the batch
209    */
210   public Object getBatch() {
211     return batch;
212   }
213 
214   /**
215    * Stter for the batch of the session.
216    *
217    * @param batch
218    *          the new batch
219    */
220   public void setBatch(Object batch) {
221     this.batch = batch;
222   }
223 
224   /**
225    * Get the request stack depth.
226    *
227    * @return - the stack depth
228    */
229   public int getRequestStackDepth() {
230     return requestStackDepth;
231   }
232 
233   /**
234    * Increment the stack depth by one.
235    */
236   public void incrementRequestStackDepth() {
237     requestStackDepth++;
238   }
239 
240   /**
241    * Decrement the stack depth by one.
242    */
243   public void decrementRequestStackDepth() {
244     requestStackDepth--;
245   }
246 
247   /**
248    * Getter to tell if a commit is required for the session.
249    *
250    * @return - true if a commit is required
251    */
252   public boolean isCommitRequired() {
253     return commitRequired;
254   }
255 
256   /**
257    * Setter to tell the session that a commit is required for the session.
258    *
259    * @param commitRequired
260    *          - the flag
261    */
262   public void setCommitRequired(boolean commitRequired) {
263     this.commitRequired = commitRequired;
264   }
265 
266   /**
267    * Checks for prepared statement for.
268    *
269    * @param sql
270    *          the sql
271    *
272    * @return true, if successful
273    */
274   public boolean hasPreparedStatementFor(String sql) {
275     return preparedStatements.containsKey(sql);
276   }
277 
278   /**
279    * Checks for prepared statement.
280    *
281    * @param ps
282    *          the ps
283    *
284    * @return true, if successful
285    */
286   public boolean hasPreparedStatement(PreparedStatement ps) {
287     return preparedStatements.containsValue(ps);
288   }
289 
290   /**
291    * Gets the prepared statement.
292    *
293    * @param sql
294    *          the sql
295    *
296    * @return the prepared statement
297    *
298    * @throws SQLException
299    *           the SQL exception
300    */
301   public PreparedStatement getPreparedStatement(String sql) throws SQLException {
302     if (!hasPreparedStatementFor(sql))
303       throw new SqlMapException("Could not get prepared statement.  This is likely a bug.");
304     PreparedStatement ps = (PreparedStatement) preparedStatements.get(sql);
305     return ps;
306   }
307 
308   /**
309    * Put prepared statement.
310    *
311    * @param delegate
312    *          the delegate
313    * @param sql
314    *          the sql
315    * @param ps
316    *          the ps
317    */
318   public void putPreparedStatement(SqlMapExecutorDelegate delegate, String sql, PreparedStatement ps) {
319     if (delegate.isStatementCacheEnabled()) {
320       if (!isInBatch()) {
321         if (hasPreparedStatementFor(sql))
322           throw new SqlMapException("Duplicate prepared statement found.  This is likely a bug.");
323         preparedStatements.put(sql, ps);
324       }
325     }
326   }
327 
328   /**
329    * Close prepared statements.
330    */
331   public void closePreparedStatements() {
332     Iterator keys = preparedStatements.keySet().iterator();
333     while (keys.hasNext()) {
334       PreparedStatement ps = (PreparedStatement) preparedStatements.get(keys.next());
335       try {
336         ps.close();
337       } catch (Exception e) {
338         // ignore -- we don't care if this fails at this point.
339       }
340     }
341     preparedStatements.clear();
342   }
343 
344   /**
345    * Cleanup.
346    */
347   public void cleanup() {
348     closePreparedStatements();
349     preparedStatements.clear();
350   }
351 
352   @Override
353   public boolean equals(Object parameterObject) {
354     if (this == parameterObject)
355       return true;
356     if (!(parameterObject instanceof SessionScope))
357       return false;
358     final SessionScope sessionScope = (SessionScope) parameterObject;
359     if (id != sessionScope.id)
360       return false;
361     return true;
362   }
363 
364   @Override
365   public int hashCode() {
366     return (int) (id ^ (id >>> 32));
367   }
368 
369   /**
370    * Method to get a unique ID.
371    *
372    * @return - the new ID
373    */
374   public synchronized static long getNextId() {
375     return nextId++;
376   }
377 
378   /**
379    * Saves the current transaction state.
380    */
381   public void saveTransactionState() {
382     savedTransactionState = transactionState;
383   }
384 
385   /**
386    * Restores the previously saved transaction state.
387    */
388   public void recallTransactionState() {
389     transactionState = savedTransactionState;
390   }
391 
392 }