View Javadoc

1   package org.apache.torque.util;
2   
3   /*
4    * Copyright 2001-2005 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License")
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import java.sql.Connection;
20  import java.sql.SQLException;
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  
25  import org.apache.torque.Torque;
26  import org.apache.torque.TorqueException;
27  
28  /***
29   * Refactored begin/commit/rollback transaction methods away from
30   * the <code>BasePeer</code>.
31   *
32   * <p>
33   * This can be used to handle cases where transaction support is optional.
34   * The second parameter of beginOptionalTransaction will determine with a
35   * transaction is used or not.
36   * If a transaction is not used, the commit and rollback methods
37   * do not have any effect. Instead it simply makes the logic easier to follow
38   * by cutting down on the if statements based solely on whether a transaction
39   * is needed or not.
40   *
41   * @author <a href="mailto:stephenh@chase3000.com">Stephen Haberman</a>
42   * @version $Id: Transaction.java 239636 2005-08-24 12:38:09Z henning $
43   */
44  public class Transaction
45  {
46  
47      /*** The log. */
48      private static Log log = LogFactory.getLog(Transaction.class);
49  
50      /***
51       * Begin a transaction.  This method will fallback gracefully to
52       * return a normal connection, if the database being accessed does
53       * not support transactions.
54       *
55       * @param dbName Name of database.
56       * @return The Connection for the transaction.
57       * @throws TorqueException Any exceptions caught during processing will be
58       *         rethrown wrapped into a TorqueException.
59       */
60      public static Connection begin(String dbName) throws TorqueException
61      {
62          return Transaction.beginOptional(dbName, true);
63      }
64  
65      /***
66       * Begin a transaction.  This method will fallback gracefully to
67       * return a normal connection, if the database being accessed does
68       * not support transactions.
69       *
70       * @param dbName Name of database.
71       * @param useTransaction If false, a transaction won't be used.
72       * @return The Connection for the transaction.
73       * @throws TorqueException Any exceptions caught during processing will be
74       *         rethrown wrapped into a TorqueException.
75       */
76      public static Connection beginOptional(String dbName,
77                                             boolean useTransaction)
78          throws TorqueException
79      {
80          Connection con = Torque.getConnection(dbName);
81          try
82          {
83              if (con.getMetaData().supportsTransactions() && useTransaction)
84              {
85                  con.setAutoCommit(false);
86              }
87          }
88          catch (SQLException e)
89          {
90              throw new TorqueException(e);
91          }
92          return con;
93      }
94  
95      /***
96       * Commit a transaction.  This method takes care of releasing the
97       * connection after the commit.  In databases that do not support
98       * transactions, it only returns the connection.
99       *
100      * @param con The Connection for the transaction.
101      * @throws TorqueException Any exceptions caught during processing will be
102      *         rethrown wrapped into a TorqueException.
103      */
104     public static void commit(Connection con) throws TorqueException
105     {
106         if (con == null)
107         {
108             throw new NullPointerException("Connection object was null. "
109                     + "This could be due to a misconfiguration of the "
110                     + "DataSourceFactory. Check the logs and Torque.properties "
111                     + "to better determine the cause.");
112         }
113 
114         try
115         {
116             if (con.getMetaData().supportsTransactions()
117                 && con.getAutoCommit() == false)
118             {
119                 con.commit();
120                 con.setAutoCommit(true);
121             }
122         }
123         catch (SQLException e)
124         {
125             throw new TorqueException(e);
126         }
127         finally
128         {
129             Torque.closeConnection(con);
130         }
131     }
132 
133     /***
134      * Roll back a transaction in databases that support transactions.
135      * It also releases the connection. In databases that do not support
136      * transactions, this method will log the attempt and release the
137      * connection.
138      *
139      * @param con The Connection for the transaction.
140      * @throws TorqueException Any exceptions caught during processing will be
141      *         rethrown wrapped into a TorqueException.
142      */
143     public static void rollback(Connection con) throws TorqueException
144     {
145         if (con == null)
146         {
147             throw new TorqueException("Connection object was null. "
148                     + "This could be due to a misconfiguration of the "
149                     + "DataSourceFactory. Check the logs and Torque.properties "
150                     + "to better determine the cause.");
151         }
152         else
153         {
154             try
155             {
156                 if (con.getMetaData().supportsTransactions()
157                     && con.getAutoCommit() == false)
158                 {
159                     con.rollback();
160                     con.setAutoCommit(true);
161                 }
162             }
163             catch (SQLException e)
164             {
165                 log.error("An attempt was made to rollback a transaction "
166                         + "but the database did not allow the operation to be "
167                         + "rolled back.", e);
168                 throw new TorqueException(e);
169             }
170             finally
171             {
172                 Torque.closeConnection(con);
173             }
174         }
175     }
176 
177     /***
178      * Roll back a transaction without throwing errors if they occur.
179      * A null Connection argument is logged at the debug level and other
180      * errors are logged at warn level.
181      *
182      * @param con The Connection for the transaction.
183      * @see rollback
184      */
185     public static void safeRollback(Connection con)
186     {
187         if (con == null)
188         {
189             log.debug("called safeRollback with null argument");
190         }
191         else
192         {
193             try
194             {
195                 Transaction.rollback(con);
196             }
197             catch (TorqueException e)
198             {
199                 log.warn("An error occured during rollback.", e);
200             }
201         }
202     }
203 }