001: /*
002: * $Header: /cvsroot/webman-cms/source/webman/com/teamkonzept/db/TKDBConnection.java,v 1.14 2002/02/16 15:32:33 alex Exp $
003: *
004: */
005: package com.teamkonzept.db;
006:
007: import java.sql.*;
008: import java.util.Vector;
009:
010: import com.teamkonzept.lib.*;
011:
012: import org.apache.log4j.Category;
013:
014: /** Klasse zur Verwaltung von Datenstrukturen, die im direkten Zusammenhang mit der
015: * JDBC-Connection stehen. Z.B f¸r die Transaktionsverwaltung verwendete Datenstrukturen.
016: *
017: * @author
018: * @version
019: */
020: public class TKDBConnection {
021: /** Logging Category */
022: private static final Category CAT = Category
023: .getInstance(TKDBConnection.class);
024:
025: /* Die Connection zur DB */
026: Connection conn;
027:
028: /** Connection manager */
029: TKDBConnectionManager connectionManager;
030:
031: public TKHashtable prepQueries = null; // of queryID, PreparedQuery for reuse of Prepared Statements
032:
033: /* Information ob noch eine als sensitve markierte Query offen ist */
034: private boolean sensitiveQueryOpen;
035:
036: /** Transaktionsstatus der Verbindung (aus Performancegründen hier gehalten)
037: JDBC definiert, dass eine Connection initial autoCommit ist
038: */
039: private boolean autoCommit = true;
040:
041: /* Enthaelt alle anderen offenen Queries. */
042: private Vector nonSensitiveQueries = new Vector();
043:
044: /* Gibt an ob eine Transaktion offen ist. */
045: private boolean transactionIsOpen = false;
046:
047: public TKDBConnection(Connection conn, TKDBConnectionManager manager) {
048: this .conn = conn;
049: this .connectionManager = manager;
050: }
051:
052: public boolean isAutoCommit() {
053: return autoCommit;
054: }
055:
056: public void setAutoCommit(boolean autoCommit) throws SQLException {
057: this .autoCommit = autoCommit;
058: conn.setAutoCommit(autoCommit);
059: }
060:
061: public boolean connectionIsClosed() throws SQLException {
062: if (conn == null) {
063: throw new TKSQLError(" No connection in TKDBConnection "); // %%change
064: }
065: return conn.isClosed();
066: }
067:
068: public TKHashtable getPrepQueries() {
069: if (prepQueries == null) {
070: prepQueries = new TKHashtable();
071: }
072: return prepQueries;
073: }
074:
075: public Connection getConnection() {
076: if (conn == null) {
077: throw new TKSQLError(" No connection in TKDBConnection "); // %% change
078: }
079: return conn;
080: }
081:
082: /** Method to store a TKPreparedQuery Object for later reuse.
083: */
084:
085: public void storePrepQuery(TKPrepQuery query, Object queryId) {
086: prepQueries.put(queryId, query);
087: CAT
088: .debug(" storePrepQuery: stored TKPrepQuery object of class "
089: + query.getClass().getName() + " for reuse ");
090: }
091:
092: public void beginTransaction() throws SQLException {
093: if (transactionIsOpen || !autoCommit) {
094: throw new TKSQLError(" Illegal nested transaction "); // change !!!
095: }
096: setAutoCommit(false);
097: transactionIsOpen = true;
098: CAT.debug(" Autocommit set to false ");
099: }
100:
101: public void commitTransaction() throws SQLException {
102: if (autoCommit || !transactionIsOpen) {
103: throw new TKSQLError(
104: "Error in transaction-management: explicit commit out of tansaction environment "); // %%change
105: }
106: cleanupTransaction();
107: conn.commit();
108: setAutoCommit(true);
109: }
110:
111: public void rollbackTransaction() throws SQLException {
112: if (!transactionIsOpen) {
113: throw new TKSQLError(
114: "Error in transaction-management: rollback outside of transaction "); // %%change
115: }
116:
117: if (!autoCommit) {
118: conn.rollback();
119: CAT.warn(" TRANSACTION ROLLED BACK ! ");
120: setAutoCommit(true);
121: } else {
122: throw new TKSQLError(" Rollback called during AutoCommit "); // %%change
123: }
124: connectionManager.closeConnection();
125: cleanupTransaction();
126: }
127:
128: /** Aufraeumen am Ende einer Transaktion:
129: * a) ‹berpr¸ft ob noch eine sensible Query offen ist, wirft dann Exceptio
130: * c) setzt transactionIsAktive auf false.
131: */
132:
133: public void cleanupTransaction() {
134: if (sensitiveQueryOpen) {
135: throw new TKSQLError(
136: " A sensitive query is still open at the end of a transaction! "); // %%change
137: }
138: transactionIsOpen = false;
139: }
140:
141: /** Meldet query als offene sensitive Query an */
142: public final void registerSensitiveQuery() {
143: if (sensitiveQueryOpen) {
144: throw new TKSQLError(
145: " Illegal attempt to execute sensitive queries interleaved! "); // %%change
146: }
147: if (transactionIsOpen == false) {
148: throw new TKSQLError(
149: " Illegal attempt to register sensitive query out of transaction environment! "); // %%change
150: }
151: sensitiveQueryOpen = true;
152: }
153:
154: /** Meldet sensible Query ab */
155: public final void deregisterSensitiveQuery() {
156: if (sensitiveQueryOpen == false) {
157: throw new TKSQLError(
158: " Illegal attempt to deregister sensitive query "); // %%change
159: } else {
160: sensitiveQueryOpen = false;
161: }
162: }
163:
164: /** Registriert query im Vector nonSensitiveQueries, und gibt den Index zur¸ck*/
165: public final int registerNonSensitiveQuery(final TKQuery query) {
166: nonSensitiveQueries.addElement(query);
167: return (nonSensitiveQueries.size() - 1);
168: }
169:
170: public final TKQuery deregisterNonSensitiveQuery(final int i) {
171: TKQuery query = (TKQuery) nonSensitiveQueries.elementAt(i);
172: nonSensitiveQueries.setElementAt(null, i);
173: return query;
174: }
175:
176: public final boolean isTransactionOpen() {
177: return transactionIsOpen;
178: }
179:
180: /** Schliesst alle noch offenen Queries im Vector nonSensitiveQueries.
181: Die Version mit Parameter erlaubt es die Queries auf unterschiedliche
182: Weise zu schliessen. Das wird z.B. von _closeConnection benoetigt.
183: Wenn connectionClose == false ist, dann f¸hrt eine Exception beim
184: Schliessen einer Query nicht zum Verbindungsabbau. Ausserdem werden
185: dann garantiert alle Queries geschlossen.
186: */
187:
188: public final void closeNonsensitiveQueries() throws SQLException {
189: closeNonsensitiveQueries(true);
190: }
191:
192: public void closeNonsensitiveQueries(final boolean connectionClose)
193:
194: throws SQLException {
195:
196: SQLException toThrow = null;
197:
198: final int num_queries = nonSensitiveQueries.size();
199: int i;
200: for (i = 0; i < num_queries; i++) {
201:
202: final TKQuery query = (TKQuery) nonSensitiveQueries
203: .elementAt(i);
204: if (query != null) {
205: if (connectionClose) {
206: query.close();
207: } else {
208: try {// Alle Queries werden geschlossen! Die letzte Exception wird weitergeworfen
209: query.specClose();
210: } catch (SQLException toCatch) {
211: toThrow = toCatch;
212: }
213: }
214: }
215: }
216: nonSensitiveQueries.removeAllElements();
217: if (toThrow != null) {
218: throw toThrow;
219: }
220: }
221:
222: }
|