KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > teamkonzept > db > TKQuery


1 /*
2  * $Header: /cvsroot/webman-cms/source/webman/com/teamkonzept/db/TKQuery.java,v 1.18 2002/02/16 15:56:51 alex Exp $
3  *
4  */

5 package com.teamkonzept.db;
6
7 import java.io.*;
8 import java.sql.*;
9
10 import com.teamkonzept.lib.*;
11 import com.teamkonzept.webman.mainint.DatabaseDefaults;
12 import org.apache.log4j.Category;
13
14 /** Abstrakte Query Klasse.
15  * Stellt eine Basis zum Erstellen und Ausführen von SQL-Queries
16  * zur Verfügung.
17  *
18  * @author
19  * @version
20  */

21 public abstract class TKQuery implements QueryConstants
22 {
23     /** Logging Category */
24     protected static final Category CAT = Category.getInstance(TKQuery.class);
25
26     public static final int DBFORM_IDENT = 69;
27     public static final int DBSTRUC_IDENT = 66;
28     public static final int DBFRAGMENT_IDENT = 67;
29
30
31     /** Verbindung zu der DB
32         */

33     protected Connection conn;
34
35         /** Objekt welches Datenstrukturen im Bezug auf die Connection enth‰lt
36         */

37     protected TKDBConnection aTKDBConnection;
38
39         /** JDBC-Statement, das der Query zugrundeliegt.
40          */

41     protected Statement stmt;
42
43         /** SQL-String, welches die Query definiert.
44          * Dieser String ist nicht unbedingt über die gesammte Lebenszeit
45          * des Objektes definiert, bzw. enthäalnt nicht zu jedem Zeitpunkt
46          * einen gültigen SQL-String.
47          */

48     protected String JavaDoc sqlString;
49
50         /** Hashtable, welche Typinformation der Query-Parameter zur
51          * Verfügung stellt.
52          * key: String parameter_name
53          * value: java.sql.Types parameter_typ
54          *
55          * @see java.sql.Types
56          */

57     protected TKHashtable paramTypes;
58
59         /** Flag welches festlegt ob die Query als senslibel betrachtet wird.
60             Als sensible sollten solche Queries markiert werde, die
61             Datenbankinhalte veraendern. Diese muessen dann innerhalb
62             einer expliziten Transaktionsumgebung ausgefuehrt werden.
63         */

64     protected boolean sensitiveQuery = false;
65
66         /* Index mit dem nichtsensitive Queries deregistriert werden.
67         */

68     protected int deregisterIndex;
69
70
71
72         /** Hashtable, welche zur jedem Query-Parametername dessen
73          * Wert verwaltet.
74          */

75     protected TKHashtable queryParams;
76     protected boolean[] setRelevants;
77
78     protected int currPos;
79     protected boolean currIsResultSet;
80
81     /** Abstrakte Methode zur Initialisierung der Query.
82      * Diese Methode wird üblicherweise von einer der beiden
83      * abgeleiteten Query-Klassen verwendet um eine <I>nicht abstrakte<I>
84      * Query zu initialisieren und mu&szlig; deshalb definiert werden.
85      *
86      * @param Connection conn Verbindung zu der DB
87      *
88      * @see com.teamkonzept.db.TKUnprepQuery
89      * @see com.teamkonzept.db.TKPrepQuery
90      */

91     public abstract void initQuery( final Connection conn );
92
93     /** Abstrakte Methode zur Initialisierung der Query.
94      * Diese Methode wird &uuml;blicherweise vom DB-Manager aufgerufen,
95      * um eine Query zu initialisieren. Sie wird
96      * u.a. implementiert von com.teamkonzept.db.TKUnprepQuery u.
97      * com.teamkonzept.db.TKPrepQuery .
98      *
99      * @param tkdbConn enth‰lt u.a. Verbindung zu der DB
100      * @param conv der der DB zugeordnete Typ-Konverter
101      * @param queryID Name der Query Klasse, erleichtert die Wiederverwendung des Objektes
102      *
103      * @see com.teamkonzept.db.TKDBManager
104      * @see com.teamkonzept.db.TKDBManager#newQuery
105      */

106     public abstract void initQuery( final TKSQLTypeConverter conv, final TKDBConnection tkdbConn, Object JavaDoc queryID);
107
108
109     /** Methode zur Initialisierung des Queryobjektes
110      *
111      * @param conn - Verbindung zur DB
112      * @param paramTypes - Liste von Parametername, Parametertyp Paaren
113      * @param setRelevants - geordnete Liste, welche angibt, welche
114      * SQl(Teil)Queries relevante ResultSets liefern.
115      */

116     public void initQuery( final Connection conn,
117                            final Object JavaDoc[][] paramTypes,
118                            final boolean[] setRelevants )
119     {
120         this.conn = conn;
121         this.setRelevants = setRelevants;
122         this.currPos = 0;
123
124         if( this instanceof SensitiveQuery ){
125             sensitiveQuery = true;
126         }
127         if ( paramTypes != null ) {
128             this.paramTypes = new TKHashtable(paramTypes);
129         } else {
130             this.paramTypes = null;
131         }
132         queryParams = new TKHashtable();
133     }
134
135
136     /** Abstrakte Methode, welche die Query ausf&uuml;hrt.
137      *
138      * @return true, falls die Query ein java.sql.ResultSet geliefert hat,
139      * false, falls das Resultat der Query ein "Update Count" ist
140      * oder leer ist.
141      *
142      * @exception java.sql.SQLException
143      */

144     public abstract boolean execute() throws SQLException;
145
146
147     /** Methode die die Query in einer eigenen Transaktion ausfuehrt.
148         Kann nur dann benutzt werden, wenn man kein Resultset braucht.
149       */

150     public void executeAsTran() throws SQLException{
151         aTKDBConnection.beginTransaction();
152         try{
153             this.execute();
154             this.close();
155         }
156         catch(SQLException t){
157             try{
158                 aTKDBConnection.rollbackTransaction();
159             }
160             catch( SQLException e ){
161                 throw e;
162             }
163         throw new TKSQLError(t.getMessage(), t);
164         }
165     }
166
167
168     /** Konstruktor zur Erstellung einer nicht initialisierten Query
169      */

170     public TKQuery() { /* NOP */ }
171
172
173     /** Methode zur Registrierung der Query fuer spaeteres
174      * automatisches Schliessen, und zur Kontrolle ob
175      * sensible Queries in einer korrekten Transaktion ausgefuehrt
176      * werden. (Wird von execute() aufgrufen)
177      * @return i > -1 bei nichtsensibler Query ein Index mit
178      * welchem die Query wieder deregistriert werden kann
179      * @return -1 bei sensibler Query
180      */

181     protected int registerQuery(){
182         int anInt;
183         if ( sensitiveQuery == false){
184             anInt = aTKDBConnection.registerNonSensitiveQuery(this);
185
186         }
187         else{
188             aTKDBConnection.registerSensitiveQuery();
189             anInt = -1;
190         }
191         return anInt;
192     }
193
194     /** Methode zum Abmelden. Wird von close() gerufen.
195      */

196     protected void deregisterQuery(){
197         TKQuery query;
198         if( sensitiveQuery){
199             aTKDBConnection.deregisterSensitiveQuery();
200         }
201         else{
202             query = aTKDBConnection.deregisterNonSensitiveQuery( deregisterIndex);
203             if( query != this) CAT.warn(" Wrong Query deregistered ");
204         }
205     }
206
207     /** Methode zum Auslesen des Ergebnisses der Query.
208      *
209      * @return java.sql.ResultSet Ergebnis der Query, nach Aufruf der
210      * Methode execute().
211      *
212      * @exception com.teamkonzept.db.TKSQLError
213      */

214     public ResultSet fetchResultSet()
215     {
216         if(TKDBManager.getDBVendor()== ORACLE || TKDBManager.getDBVendor()==POSTGRESQL){
217             try{
218                 return stmt.getResultSet();
219             } catch (SQLException sqle) {
220                 printSqlException(sqle, "fetchResultSet");
221             }
222         }
223
224         if(setRelevants== null) return null;
225
226         ResultSet rs = null;
227
228         FETCH:
229         while( currPos < setRelevants.length ) {
230             try {
231                 if ((currPos != 0) || (!currIsResultSet) ) {
232                     while (
233                             (!(currIsResultSet = stmt.getMoreResults())) &&
234                             (stmt.getUpdateCount() != -1)) {
235                         CAT.debug("POS " + currPos + " NO RS OR UPDATECOUNT<BR>");
236                     }
237                 }
238
239                 if (currIsResultSet) {
240                     rs = stmt.getResultSet();
241                         CAT.debug("POS " + currPos + " RS FOUND <BR>");
242                 } else {
243                         CAT.debug("POS " + currPos + " END <BR>");
244                     currPos = setRelevants.length;
245                     break FETCH;
246                 }
247
248                 if (setRelevants[currPos++]) {
249                         CAT.debug("POS " + (currPos-1) + " RS RELEVANT <BR>");
250                     break FETCH;
251                 } else {
252                         CAT.debug("POS " + (currPos-1) + " NOT RELEVANT, RS SET NULL<BR>");
253                     rs = null;
254                 }
255
256             } catch (SQLException sqle) {
257                 printSqlException(sqle, "fetchResultSet");
258             }
259         }
260
261         return rs;
262     }
263
264
265
266     /** Wie specClose, aber mit Fehlerbehandlung.
267         Innerhalb von Transaktionen wird der Verbindungsabbau
268         der Rollback - Methode ueberlassen.
269      */

270
271     public void close()throws SQLException{
272         try{
273
274             specClose();
275
276         }
277         catch(SQLException e){
278             try{
279                 if(!aTKDBConnection.isTransactionOpen()){
280                     TKDBManager.closeConnection();
281                 }
282             }
283             catch(SQLException s){
284                 CAT.debug(s.getMessage());
285             }
286             printSqlException(e, " close PrepQuery failed ");
287         }
288     }
289
290
291
292     /** Methode um die Query abzuschliessen und bei
293      * TKDConnection Objekt abzumelden
294      *
295      */

296     public abstract void specClose() throws SQLException;
297
298
299
300     /** Holt alle Results (das sind ResultSets und UpdateCounts)
301      * ab. Das ist z.B. erforderlich damit ein PreparedStatement als
302      * abgeschlossen gilt.
303      * ACHTUNG: mit getResultSet() anstelle von getMoreResults()
304      * h‰tte diese Methode nicht funktuiniert! Ein Bug?
305      *
306      * @exception java.sql.SQLException
307      */

308     public void throwawayResults() throws SQLException{
309         /* non jdbc conform behaviour */
310         if( TKDBManager.getDBVendor() == POSTGRESQL) return;
311         if( TKDBManager.getDBVendor() == ORACLE) return;
312         if( TKDBManager.getDBVendor() == DONTKNOW) return;
313
314         if (stmt != null){
315             while( stmt.getMoreResults() || (stmt.getUpdateCount() != -1 ) ) {
316             }
317         }
318     }
319
320
321     /** Methode, welche einem Query-Parameter einen Wert zuweist.
322      *
323      * @param java.lang.String param - Name des Parameters
324      * @param java.lang.Object val - Wert des Parameters
325      */

326     public void setQueryParams( String JavaDoc param, Object JavaDoc val)
327     {
328         if (val == null) {
329             queryParams.put(param, TKNull.NULL);
330         } else {
331             queryParams.put(param, val);
332         }
333     }
334
335     /** Methode, welche eine SQLException in einen TKSQLError
336      * konvertiert und diesen wirft.
337      *
338      * @param java.sql.SQLException sqle - die zu konvertierende SQLException
339      * @param java.lang.String s - String, welcher beschreibt, bei welcher Aktion
340      * die Ausnahme aufgetreten ist.
341      *
342      * @exception com.teamkonzept.db.TKSQLError
343      */

344     public void printSqlException(SQLException sqle, String JavaDoc s)
345     {
346         throw new TKSQLError(
347             " Query: " + this.getClass().getName() +
348             " STMT: " + sqlString +
349             " Action: " + s +
350             " Message: " + sqle.getMessage(), sqle);
351     }
352 }
353
354
355
Popular Tags