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
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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 }