KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > transaction > JDBCTransaction


1 //$Id: JDBCTransaction.java,v 1.12 2005/05/03 21:50:17 oneovthafew Exp $
2
package org.hibernate.transaction;
3
4 import java.sql.SQLException JavaDoc;
5 import java.util.ArrayList JavaDoc;
6 import java.util.List JavaDoc;
7
8 import javax.transaction.Status JavaDoc;
9 import javax.transaction.Synchronization JavaDoc;
10
11 import org.apache.commons.logging.Log;
12 import org.apache.commons.logging.LogFactory;
13
14 import org.hibernate.HibernateException;
15 import org.hibernate.Transaction;
16 import org.hibernate.TransactionException;
17 import org.hibernate.jdbc.JDBCContext;
18
19 /**
20  * Implements a basic transaction strategy for JDBC connections.This is the
21  * default <tt>Transaction</tt> implementation used if none is explicitly
22  * specified.
23  * @author Anton van Straaten, Gavin King
24  */

25 public class JDBCTransaction implements Transaction {
26
27     private static final Log log = LogFactory.getLog(JDBCTransaction.class);
28
29     private final JDBCContext jdbcContext;
30     private final TransactionFactory.Context transactionContext;
31
32     private boolean toggleAutoCommit;
33     private boolean rolledBack;
34     private boolean committed;
35     private boolean begun;
36     private boolean commitFailed;
37     private List JavaDoc synchronizations;
38     private boolean callback;
39
40     public JDBCTransaction(JDBCContext jdbcContext, TransactionFactory.Context transactionContext) {
41         this.jdbcContext = jdbcContext;
42         this.transactionContext = transactionContext;
43     }
44
45     public void begin() throws HibernateException {
46         log.debug("begin");
47
48         try {
49             toggleAutoCommit = jdbcContext.connection().getAutoCommit();
50             if ( log.isDebugEnabled() ) log.debug("current autocommit status: " + toggleAutoCommit);
51             if (toggleAutoCommit) {
52                 log.debug("disabling autocommit");
53                 jdbcContext.connection().setAutoCommit(false);
54             }
55         }
56         catch (SQLException JavaDoc e) {
57             log.error("JDBC begin failed", e);
58             throw new TransactionException("JDBC begin failed: ", e);
59         }
60
61         callback = jdbcContext.registerCallbackIfNecessary();
62
63         begun = true;
64     }
65     
66     private void closeIfRequired() throws HibernateException {
67         if ( callback && transactionContext.shouldAutoClose() && transactionContext.isOpen() ) {
68             try {
69                 transactionContext.managedClose();
70             }
71             catch (HibernateException he) {
72                 log.error("Could not close session", he);
73                 //swallow, the transaction was finished
74
}
75         }
76     }
77
78     public void commit() throws HibernateException {
79         if (!begun) {
80             throw new TransactionException("Transaction not successfully started");
81         }
82
83         log.debug("commit");
84
85         if ( !transactionContext.isFlushModeNever() && callback ) {
86             transactionContext.managedFlush(); //if an exception occurs during flush, user must call rollback()
87
}
88
89         beforeTransactionCompletion();
90         if ( callback ) {
91             jdbcContext.beforeTransactionCompletion( this );
92         }
93
94         try {
95             commitAndResetAutoCommit();
96             log.debug("committed JDBC Connection");
97             committed = true;
98             if ( callback ) {
99                 jdbcContext.afterTransactionCompletion( true, this );
100             }
101             afterTransactionCompletion( Status.STATUS_COMMITTED );
102         }
103         catch (SQLException JavaDoc e) {
104             log.error("JDBC commit failed", e);
105             commitFailed = true;
106             if ( callback ) {
107                 jdbcContext.afterTransactionCompletion( false, this );
108             }
109             afterTransactionCompletion( Status.STATUS_UNKNOWN );
110             throw new TransactionException("JDBC commit failed", e);
111         }
112         finally {
113             closeIfRequired();
114         }
115     }
116
117     private void commitAndResetAutoCommit() throws SQLException JavaDoc {
118         try {
119             jdbcContext.connection().commit();
120         }
121         finally {
122             toggleAutoCommit();
123         }
124     }
125
126     public void rollback() throws HibernateException {
127
128         if (!begun) {
129             throw new TransactionException("Transaction not successfully started");
130         }
131
132         log.debug("rollback");
133
134         if (!commitFailed) {
135
136             beforeTransactionCompletion();
137             if ( callback ) {
138                 jdbcContext.beforeTransactionCompletion( this );
139             }
140
141             try {
142                 rollbackAndResetAutoCommit();
143                 log.debug("rolled back JDBC Connection");
144                 rolledBack = true;
145                 afterTransactionCompletion(Status.STATUS_ROLLEDBACK);
146             }
147             catch (SQLException JavaDoc e) {
148                 log.error("JDBC rollback failed", e);
149                 afterTransactionCompletion(Status.STATUS_UNKNOWN);
150                 throw new TransactionException("JDBC rollback failed", e);
151             }
152             finally {
153                 if ( callback ) {
154                     jdbcContext.afterTransactionCompletion( false, this );
155                 }
156                 closeIfRequired();
157             }
158         }
159     }
160
161     private void rollbackAndResetAutoCommit() throws SQLException JavaDoc {
162         try {
163             jdbcContext.connection().rollback();
164         }
165         finally {
166             toggleAutoCommit();
167         }
168     }
169
170     private void toggleAutoCommit() {
171         try {
172             if (toggleAutoCommit) {
173                 log.debug("re-enabling autocommit");
174                 jdbcContext.connection().setAutoCommit( true );
175             }
176         }
177         catch (Exception JavaDoc sqle) {
178             log.error("Could not toggle autocommit", sqle);
179             //swallow it (the transaction _was_ successful or successfully rolled back)
180
}
181     }
182
183     public boolean wasRolledBack() {
184         return rolledBack;
185     }
186     
187     public boolean wasCommitted() {
188         return committed;
189     }
190
191     public boolean isActive() {
192         return begun && ! ( rolledBack || committed | commitFailed );
193     }
194     
195     public void registerSynchronization(Synchronization JavaDoc sync) throws HibernateException {
196         if (sync==null) throw new NullPointerException JavaDoc("null Synchronization");
197         if (synchronizations==null) {
198             synchronizations = new ArrayList JavaDoc();
199         }
200         synchronizations.add(sync);
201     }
202     
203     private void beforeTransactionCompletion() {
204         if (synchronizations!=null) {
205             for ( int i=0; i<synchronizations.size(); i++ ) {
206                 Synchronization JavaDoc sync = (Synchronization JavaDoc) synchronizations.get(i);
207                 try {
208                     sync.beforeCompletion();
209                 }
210                 catch (Throwable JavaDoc t) {
211                     log.error("exception calling user Synchronization", t);
212                 }
213             }
214         }
215     }
216
217     private void afterTransactionCompletion(int status) {
218         if (synchronizations!=null) {
219             for ( int i=0; i<synchronizations.size(); i++ ) {
220                 Synchronization JavaDoc sync = (Synchronization JavaDoc) synchronizations.get(i);
221                 try {
222                     sync.afterCompletion(status);
223                 }
224                 catch (Throwable JavaDoc t) {
225                     log.error("exception calling user Synchronization", t);
226                 }
227             }
228         }
229     }
230 }
231
Popular Tags