View Javadoc
1   /*
2    * Copyright 2004-2025 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      TransactionState state = sessionScope.getTransactionState();
70      if (state == TransactionState.STATE_STARTED) {
71        throw new TransactionException(
72            "TransactionManager could not start a new transaction.  " + "A transaction is already started.");
73      }
74      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      Transaction 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     }
107     if (state != TransactionState.STATE_STARTED && state != TransactionState.STATE_COMMITTED) {
108       throw new TransactionException("TransactionManager could not commit.  No transaction is started.");
109     }
110     if (sessionScope.isCommitRequired() || config.isForceCommit()) {
111       trans.commit();
112       sessionScope.setCommitRequired(false);
113     }
114     sessionScope.setTransactionState(TransactionState.STATE_COMMITTED);
115   }
116 
117   /**
118    * End.
119    *
120    * @param sessionScope
121    *          the session scope
122    *
123    * @throws SQLException
124    *           the SQL exception
125    * @throws TransactionException
126    *           the transaction exception
127    */
128   public void end(SessionScope sessionScope) throws SQLException, TransactionException {
129     Transaction trans = sessionScope.getTransaction();
130     TransactionState state = sessionScope.getTransactionState();
131 
132     if (state == TransactionState.STATE_USER_PROVIDED) {
133       throw new TransactionException("TransactionManager could not end this transaction.  "
134           + "A user provided connection is currently being used by this session.  "
135           + "You must call the rollback() method of the Connection directly.  "
136           + "The calling .setUserConnection (null) will clear the user provided transaction.");
137     }
138 
139     try {
140       if (trans != null) {
141         try {
142           if (state != TransactionState.STATE_COMMITTED
143               && (sessionScope.isCommitRequired() || config.isForceCommit())) {
144             trans.rollback();
145             sessionScope.setCommitRequired(false);
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 }