1 package org.apache.torque.util;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 }