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.transaction;
17  
18  import com.ibatis.sqlmap.engine.scope.SessionScope;
19  
20  import java.sql.SQLException;
21  
22  /**
23   * The Class TransactionManager.
24   */
25  public class TransactionManager {
26  
27    /** The config. */
28    private TransactionConfig config;
29  
30    /**
31     * Instantiates a new transaction manager.
32     *
33     * @param transactionConfig
34     *          the transaction config
35     */
36    public TransactionManager(TransactionConfig transactionConfig) {
37      this.config = transactionConfig;
38    }
39  
40    /**
41     * Begin.
42     *
43     * @param sessionScope
44     *          the session scope
45     *
46     * @throws SQLException
47     *           the SQL exception
48     * @throws TransactionException
49     *           the transaction exception
50     */
51    public void begin(SessionScope sessionScope) throws SQLException, TransactionException {
52      begin(sessionScope, IsolationLevel.UNSET_ISOLATION_LEVEL);
53    }
54  
55    /**
56     * Begin.
57     *
58     * @param sessionScope
59     *          the session scope
60     * @param transactionIsolation
61     *          the transaction isolation
62     *
63     * @throws SQLException
64     *           the SQL exception
65     * @throws TransactionException
66     *           the transaction exception
67     */
68    public void begin(SessionScope sessionScope, int transactionIsolation) throws SQLException, TransactionException {
69      Transaction trans = sessionScope.getTransaction();
70      TransactionState state = sessionScope.getTransactionState();
71      if (state == TransactionState.STATE_STARTED) {
72        throw new TransactionException(
73            "TransactionManager could not start a new transaction.  " + "A transaction is already started.");
74      } else if (state == TransactionState.STATE_USER_PROVIDED) {
75        throw new TransactionException("TransactionManager could not start a new transaction.  "
76            + "A user provided connection is currently being used by this session.  "
77            + "The calling .setUserConnection (null) will clear the user provided transaction.");
78      }
79  
80      trans = config.newTransaction(transactionIsolation);
81      sessionScope.setCommitRequired(false);
82  
83      sessionScope.setTransaction(trans);
84      sessionScope.setTransactionState(TransactionState.STATE_STARTED);
85    }
86  
87    /**
88     * Commit.
89     *
90     * @param sessionScope
91     *          the session scope
92     *
93     * @throws SQLException
94     *           the SQL exception
95     * @throws TransactionException
96     *           the transaction exception
97     */
98    public void commit(SessionScope sessionScope) throws SQLException, TransactionException {
99      Transaction trans = sessionScope.getTransaction();
100     TransactionState state = sessionScope.getTransactionState();
101     if (state == TransactionState.STATE_USER_PROVIDED) {
102       throw new TransactionException("TransactionManager could not commit.  "
103           + "A user provided connection is currently being used by this session.  "
104           + "You must call the commit() method of the Connection directly.  "
105           + "The calling .setUserConnection (null) will clear the user provided transaction.");
106     } else if (state != TransactionState.STATE_STARTED && state != TransactionState.STATE_COMMITTED) {
107       throw new TransactionException("TransactionManager could not commit.  No transaction is started.");
108     }
109     if (sessionScope.isCommitRequired() || config.isForceCommit()) {
110       trans.commit();
111       sessionScope.setCommitRequired(false);
112     }
113     sessionScope.setTransactionState(TransactionState.STATE_COMMITTED);
114   }
115 
116   /**
117    * End.
118    *
119    * @param sessionScope
120    *          the session scope
121    *
122    * @throws SQLException
123    *           the SQL exception
124    * @throws TransactionException
125    *           the transaction exception
126    */
127   public void end(SessionScope sessionScope) throws SQLException, TransactionException {
128     Transaction trans = sessionScope.getTransaction();
129     TransactionState state = sessionScope.getTransactionState();
130 
131     if (state == TransactionState.STATE_USER_PROVIDED) {
132       throw new TransactionException("TransactionManager could not end this transaction.  "
133           + "A user provided connection is currently being used by this session.  "
134           + "You must call the rollback() method of the Connection directly.  "
135           + "The calling .setUserConnection (null) will clear the user provided transaction.");
136     }
137 
138     try {
139       if (trans != null) {
140         try {
141           if (state != TransactionState.STATE_COMMITTED) {
142             if (sessionScope.isCommitRequired() || config.isForceCommit()) {
143               trans.rollback();
144               sessionScope.setCommitRequired(false);
145             }
146           }
147         } finally {
148           sessionScope.closePreparedStatements();
149           trans.close();
150         }
151       }
152     } finally {
153       sessionScope.setTransaction(null);
154       sessionScope.setTransactionState(TransactionState.STATE_ENDED);
155     }
156   }
157 
158   /**
159    * Gets the config.
160    *
161    * @return the config
162    */
163   public TransactionConfig getConfig() {
164     return config;
165   }
166 
167 }