View Javadoc

1   package org.apache.torque.util;
2   
3   /* ====================================================================
4    * The Apache Software License, Version 1.1
5    *
6    * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
7    * reserved.
8    *
9    * Redistribution and use in source and binary forms, with or without
10   * modification, are permitted provided that the following conditions
11   * are met:
12   *
13   * 1. Redistributions of source code must retain the above copyright
14   *    notice, this list of conditions and the following disclaimer.
15   *
16   * 2. Redistributions in binary form must reproduce the above copyright
17   *    notice, this list of conditions and the following disclaimer in
18   *    the documentation and/or other materials provided with the
19   *    distribution.
20   *
21   * 3. The end-user documentation included with the redistribution,
22   *    if any, must include the following acknowledgment:
23   *       "This product includes software developed by the
24   *        Apache Software Foundation (http://www.apache.org/)."
25   *    Alternately, this acknowledgment may appear in the software itself,
26   *    if and wherever such third-party acknowledgments normally appear.
27   *
28   * 4. The names "Apache" and "Apache Software Foundation" and
29   *    "Apache Turbine" must not be used to endorse or promote products
30   *    derived from this software without prior written permission. For
31   *    written permission, please contact apache@apache.org.
32   *
33   * 5. Products derived from this software may not be called "Apache",
34   *    "Apache Turbine", nor may "Apache" appear in their name, without
35   *    prior written permission of the Apache Software Foundation.
36   *
37   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48   * SUCH DAMAGE.
49   * ====================================================================
50   *
51   * This software consists of voluntary contributions made by many
52   * individuals on behalf of the Apache Software Foundation.  For more
53   * information on the Apache Software Foundation, please see
54   * <http://www.apache.org/>.
55   */
56  
57  import java.sql.Connection;
58  import java.sql.SQLException;
59  
60  import org.apache.commons.logging.Log;
61  import org.apache.commons.logging.LogFactory;
62  
63  import org.apache.torque.Torque;
64  import org.apache.torque.TorqueException;
65  
66  /***
67   * Refactored begin/commit/rollback transaction methods away from
68   * the <code>BasePeer</code>.
69   *
70   * <p>
71   * This can be used to handle cases where transaction support is optional.
72   * The second parameter of beginOptionalTransaction will determine with a 
73   * transaction is used or not. 
74   * If a transaction is not used, the commit and rollback methods
75   * do not have any effect. Instead it simply makes the logic easier to follow
76   * by cutting down on the if statements based solely on whether a transaction
77   * is needed or not.
78   *
79   * @author <a href="mailto:stephenh@chase3000.com">Stephen Haberman</a>
80   * @version $Id: Transaction.java,v 1.9 2003/08/03 17:41:04 jmcnally Exp $
81   */
82  public class Transaction
83  {
84  
85      /*** The log. */
86      private static Log log = LogFactory.getLog(Transaction.class);
87  
88      /***
89       * Begin a transaction.  This method will fallback gracefully to
90       * return a normal connection, if the database being accessed does
91       * not support transactions.
92       *
93       * @param dbName Name of database.
94       * @return The Connection for the transaction.
95       * @throws TorqueException Any exceptions caught during processing will be
96       *         rethrown wrapped into a TorqueException.
97       */
98      public static Connection begin(String dbName) throws TorqueException
99      {
100         return Transaction.beginOptional(dbName, true);
101     }
102 
103     /***
104      * Begin a transaction.  This method will fallback gracefully to
105      * return a normal connection, if the database being accessed does
106      * not support transactions.
107      *
108      * @param dbName Name of database.
109      * @param useTransaction If false, a transaction won't be used.
110      * @return The Connection for the transaction.
111      * @throws TorqueException Any exceptions caught during processing will be
112      *         rethrown wrapped into a TorqueException.
113      */
114     public static Connection beginOptional(String dbName,
115                                            boolean useTransaction)
116         throws TorqueException
117     {
118         Connection con = Torque.getConnection(dbName);
119         try
120         {
121             if (con.getMetaData().supportsTransactions() && useTransaction)
122             {
123                 con.setAutoCommit(false);
124             }
125         }
126         catch (SQLException e)
127         {
128             throw new TorqueException(e);
129         }
130         return con;
131     }
132 
133     /***
134      * Commit a transaction.  This method takes care of releasing the
135      * connection after the commit.  In databases that do not support
136      * transactions, it only returns the connection.
137      *
138      * @param con The Connection for the transaction.
139      * @throws TorqueException Any exceptions caught during processing will be
140      *         rethrown wrapped into a TorqueException.
141      */
142     public static void commit(Connection con) throws TorqueException
143     {
144         if (con == null)
145         {
146             throw new NullPointerException("Connection object was null. "
147                     + "This could be due to a misconfiguration of the "
148                     + "DataSourceFactory. Check the logs and Torque.properties "
149                     + "to better determine the cause.");
150         }
151 
152         try
153         {
154             if (con.getMetaData().supportsTransactions()
155                 && con.getAutoCommit() == false)
156             {
157                 con.commit();
158                 con.setAutoCommit(true);
159             }
160         }
161         catch (SQLException e)
162         {
163             throw new TorqueException(e);
164         }
165         finally
166         {
167             Torque.closeConnection(con);
168         }
169     }
170 
171     /***
172      * Roll back a transaction in databases that support transactions.
173      * It also releases the connection. In databases that do not support
174      * transactions, this method will log the attempt and release the
175      * connection.
176      *
177      * @param con The Connection for the transaction.
178      * @throws TorqueException Any exceptions caught during processing will be
179      *         rethrown wrapped into a TorqueException.
180      */
181     public static void rollback(Connection con) throws TorqueException
182     {
183         if (con == null)
184         {
185             throw new TorqueException("Connection object was null. "
186                     + "This could be due to a misconfiguration of the "
187                     + "DataSourceFactory. Check the logs and Torque.properties "
188                     + "to better determine the cause.");
189         }
190         else
191         {
192             try
193             {
194                 if (con.getMetaData().supportsTransactions()
195                     && con.getAutoCommit() == false)
196                 {
197                     con.rollback();
198                     con.setAutoCommit(true);
199                 }
200             }
201             catch (SQLException e)
202             {
203                 log.error("An attempt was made to rollback a transaction "
204                         + "but the database did not allow the operation to be "
205                         + "rolled back.", e);
206                 throw new TorqueException(e);
207             }
208             finally
209             {
210                 Torque.closeConnection(con);
211             }
212         }
213     }
214 
215     /***
216      * Roll back a transaction without throwing errors if they occur.
217      * A null Connection argument is logged at the debug level and other
218      * errors are logged at warn level.
219      * 
220      * @param con The Connection for the transaction.
221      * @see safeRollback
222      */
223     public static void safeRollback(Connection con) 
224     {
225         if (con == null) 
226         {
227             log.debug("called safeRollback with null argument");
228         }
229         else 
230         {
231             try
232             {
233                 Transaction.rollback(con);
234             }
235             catch (TorqueException e)
236             {
237                 log.warn("An error occured during rollback.", e);
238             }
239         }   
240     }
241 }