1 package org.apache.torque.util;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.sql.Connection;
23 import java.sql.SQLException;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27
28 import org.apache.torque.Torque;
29 import org.apache.torque.TorqueException;
30
31 /***
32 * Refactored begin/commit/rollback transaction methods away from
33 * the <code>BasePeer</code>.
34 *
35 * <p>
36 * This can be used to handle cases where transaction support is optional.
37 * The second parameter of beginOptionalTransaction will determine with a
38 * transaction is used or not.
39 * If a transaction is not used, the commit and rollback methods
40 * do not have any effect. Instead it simply makes the logic easier to follow
41 * by cutting down on the if statements based solely on whether a transaction
42 * is needed or not.
43 *
44 * @author <a href="mailto:stephenh@chase3000.com">Stephen Haberman</a>
45 * @version $Id: Transaction.java 476550 2006-11-18 16:08:37Z tfischer $
46 */
47 public final class Transaction
48 {
49
50 /*** The log. */
51 private static Log log = LogFactory.getLog(Transaction.class);
52
53 /***
54 * Private constructor to prevent instantiation.
55 *
56 * Class contains only static method ans should therefore not be
57 * instantiated.
58 */
59 private Transaction()
60 {
61 }
62
63 /***
64 * Begin a transaction for the default database.
65 * This method will fallback gracefully to
66 * return a normal connection, if the database being accessed does
67 * not support transactions.
68 *
69 * @return The Connection for the transaction.
70 * @throws TorqueException Any exceptions caught during processing will be
71 * rethrown wrapped into a TorqueException.
72 */
73 public static Connection begin() throws TorqueException
74 {
75 return Transaction.begin(Torque.getDefaultDB());
76 }
77
78 /***
79 * Begin a transaction. This method will fallback gracefully to
80 * return a normal connection, if the database being accessed does
81 * not support transactions.
82 *
83 * @param dbName Name of database.
84 * @return The Connection for the transaction.
85 * @throws TorqueException Any exceptions caught during processing will be
86 * rethrown wrapped into a TorqueException.
87 */
88 public static Connection begin(String dbName) throws TorqueException
89 {
90 return Transaction.beginOptional(dbName, true);
91 }
92
93 /***
94 * Begin a transaction. This method will fallback gracefully to
95 * return a normal connection, if the database being accessed does
96 * not support transactions.
97 *
98 * @param dbName Name of database.
99 * @param useTransaction If false, a transaction won't be used.
100 * @return 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 Connection beginOptional(String dbName,
105 boolean useTransaction)
106 throws TorqueException
107 {
108 Connection con = Torque.getConnection(dbName);
109 try
110 {
111 if (con.getMetaData().supportsTransactions() && useTransaction)
112 {
113 con.setAutoCommit(false);
114 }
115 }
116 catch (SQLException e)
117 {
118 throw new TorqueException(e);
119 }
120 return con;
121 }
122
123 /***
124 * Commit a transaction. This method takes care of releasing the
125 * connection after the commit. In databases that do not support
126 * transactions, it only returns the connection.
127 *
128 * @param con The Connection for the transaction.
129 * @throws TorqueException Any exceptions caught during processing will be
130 * rethrown wrapped into a TorqueException.
131 */
132 public static void commit(Connection con) throws TorqueException
133 {
134 if (con == null)
135 {
136 throw new NullPointerException("Connection object was null. "
137 + "This could be due to a misconfiguration of the "
138 + "DataSourceFactory. Check the logs and Torque.properties "
139 + "to better determine the cause.");
140 }
141
142 try
143 {
144 if (con.getMetaData().supportsTransactions()
145 && con.getAutoCommit() == false)
146 {
147 con.commit();
148 con.setAutoCommit(true);
149 }
150 }
151 catch (SQLException e)
152 {
153 throw new TorqueException(e);
154 }
155 finally
156 {
157 Torque.closeConnection(con);
158 }
159 }
160
161 /***
162 * Roll back a transaction in databases that support transactions.
163 * It also releases the connection. In databases that do not support
164 * transactions, this method will log the attempt and release the
165 * connection.
166 *
167 * @param con The Connection for the transaction.
168 * @throws TorqueException Any exceptions caught during processing will be
169 * rethrown wrapped into a TorqueException.
170 */
171 public static void rollback(Connection con) throws TorqueException
172 {
173 if (con == null)
174 {
175 throw new TorqueException("Connection object was null. "
176 + "This could be due to a misconfiguration of the "
177 + "DataSourceFactory. Check the logs and Torque.properties "
178 + "to better determine the cause.");
179 }
180 else
181 {
182 try
183 {
184 if (con.getMetaData().supportsTransactions()
185 && con.getAutoCommit() == false)
186 {
187 con.rollback();
188 con.setAutoCommit(true);
189 }
190 }
191 catch (SQLException e)
192 {
193 log.error("An attempt was made to rollback a transaction "
194 + "but the database did not allow the operation to be "
195 + "rolled back.", e);
196 throw new TorqueException(e);
197 }
198 finally
199 {
200 Torque.closeConnection(con);
201 }
202 }
203 }
204
205 /***
206 * Roll back a transaction without throwing errors if they occur.
207 * A null Connection argument is logged at the debug level and other
208 * errors are logged at warn level.
209 *
210 * @param con The Connection for the transaction.
211 * @see Transaction#rollback(Connection)
212 */
213 public static void safeRollback(Connection con)
214 {
215 if (con == null)
216 {
217 log.debug("called safeRollback with null argument");
218 }
219 else
220 {
221 try
222 {
223 Transaction.rollback(con);
224 }
225 catch (TorqueException e)
226 {
227 log.warn("An error occured during rollback.", e);
228 }
229 }
230 }
231 }