View Javadoc

1   package com.workingdogs.village;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.sql.Connection;
23  import java.sql.SQLException;
24  import java.util.Enumeration;
25  
26  /***
27   * This class is used for doing select/insert/delete/update on the database. A TableDataSet cannot be used to join multiple tables
28   * for an update, if you need join functionality on a select, you should use a <a href="QueryDataSet.html">QueryDataSet</a>.
29   *
30   * <P>
31   * Here is an example usage for this code that gets the first 10 records where column "a" = 1:
32   * <PRE>
33   *  KeyDef kd = new KeyDef().setAttrib("column");
34   *  TableDataSet tds = new TableDataSet(connection, "table_name", kd );
35   *  tds.where ("a=1" ); // WHERE a = 1
36   *  tds.fetchRecords(10); // fetch first 10 records where column a=1
37   *  for ( int i=0;i< tds.size(); i++ )
38   *  {
39   *  Record rec = tds.getRecord(i); // zero based
40   *  String columnA = rec.getValue("a");
41   *  if ( columnA.equals ("1") )
42   *  System.out.print ("We got a column!");
43   *  }
44   *  tds.close();
45   *  </PRE>
46   * </p>
47   *
48   * <P>
49   * It is important to remember to always close() the TableDataSet when you are finished with it.
50   * </p>
51   *
52   * <P>
53   * As you can see, using a TableDataSet makes doing selects from the database trivial. You do not need to write any SQL and it
54   * makes it easy to cache a TableDataSet for future use within your application.
55   * </p>
56   *
57   * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
58   * @version $Revision: 568 $
59   */
60  public class TableDataSet
61          extends DataSet
62  {
63      /*** the value for the sql where clause */
64      private String where = null;
65  
66      /*** the value for the sql order by clause */
67      private String order = null;
68  
69      /*** the value for the sql other clause */
70      private String other = null;
71  
72      // by default this is false;
73  
74      /*** TODO: DOCUMENT ME! */
75      private boolean refreshOnSave = false;
76  
77      /***
78       * Default constructor.
79       *
80       * @exception SQLException
81       * @exception DataSetException
82       */
83      public TableDataSet()
84              throws SQLException, DataSetException
85      {
86          super();
87      }
88  
89      /***
90       * Creates a new TableDataSet object.
91       *
92       * @param conn TODO: DOCUMENT ME!
93       * @param tableName TODO: DOCUMENT ME!
94       *
95       * @throws SQLException TODO: DOCUMENT ME!
96       * @throws DataSetException TODO: DOCUMENT ME!
97       */
98      public TableDataSet(Connection conn, String tableName)
99              throws SQLException, DataSetException
100     {
101         super(conn, tableName);
102     }
103 
104     /***
105      * Creates a new TableDataSet object.
106      *
107      * @param conn TODO: DOCUMENT ME!
108      * @param schema TODO: DOCUMENT ME!
109      * @param keydef TODO: DOCUMENT ME!
110      *
111      * @throws SQLException TODO: DOCUMENT ME!
112      * @throws DataSetException TODO: DOCUMENT ME!
113      */
114     public TableDataSet(Connection conn, Schema schema, KeyDef keydef)
115             throws SQLException, DataSetException
116     {
117         super(conn, schema, keydef);
118     }
119 
120     /***
121      * Creates a new TableDataSet object.
122      *
123      * @param conn TODO: DOCUMENT ME!
124      * @param tableName TODO: DOCUMENT ME!
125      * @param keydef TODO: DOCUMENT ME!
126      *
127      * @throws SQLException TODO: DOCUMENT ME!
128      * @throws DataSetException TODO: DOCUMENT ME!
129      */
130     public TableDataSet(Connection conn, String tableName, KeyDef keydef)
131             throws SQLException, DataSetException
132     {
133         super(conn, tableName, keydef);
134     }
135 
136     /***
137      * Creates a new TableDataSet object.
138      *
139      * @param conn TODO: DOCUMENT ME!
140      * @param tableName TODO: DOCUMENT ME!
141      * @param columns TODO: DOCUMENT ME!
142      *
143      * @throws SQLException TODO: DOCUMENT ME!
144      * @throws DataSetException TODO: DOCUMENT ME!
145      */
146     public TableDataSet(Connection conn, String tableName, String columns)
147             throws SQLException, DataSetException
148     {
149         super(conn, tableName, columns);
150     }
151 
152     /***
153      * Creates a new TableDataSet object.
154      *
155      * @param conn TODO: DOCUMENT ME!
156      * @param tableName TODO: DOCUMENT ME!
157      * @param columns TODO: DOCUMENT ME!
158      * @param keydef TODO: DOCUMENT ME!
159      *
160      * @throws SQLException TODO: DOCUMENT ME!
161      * @throws DataSetException TODO: DOCUMENT ME!
162      */
163     public TableDataSet(Connection conn, String tableName, String columns, KeyDef keydef)
164             throws SQLException, DataSetException
165     {
166         super(conn, tableName, columns, keydef);
167     }
168 
169     /***
170      * Fetch start to max records. start is at Record 0
171      *
172      * @param start
173      * @param max
174      *
175      * @return an instance of myself
176      *
177      * @exception SQLException
178      * @exception DataSetException
179      */
180     public DataSet fetchRecords(int start, int max)
181             throws SQLException, DataSetException
182     {
183         buildSelectString();
184 
185         return super.fetchRecords(start, max);
186     }
187 
188     /***
189      * Saves all the records in the DataSet.
190      *
191      * @return total number of records updated/inserted/deleted
192      *
193      * @throws SQLException TODO: DOCUMENT ME!
194      * @throws DataSetException TODO: DOCUMENT ME!
195      */
196     public int save()
197             throws SQLException, DataSetException
198     {
199         return save(connection(), false);
200     }
201 
202     /***
203      * Saves all the records in the DataSet with the intransaction boolean value.
204      *
205      * @param intransaction TODO: DOCUMENT ME!
206      *
207      * @return total number of records updated/inserted/deleted
208      *
209      * @throws SQLException TODO: DOCUMENT ME!
210      * @throws DataSetException TODO: DOCUMENT ME!
211      */
212     public int save(boolean intransaction)
213             throws SQLException, DataSetException
214     {
215         return save(connection(), intransaction);
216     }
217 
218     /***
219      * Saves all the records in the DataSet with the given connection and intransaction boolean value.
220      *
221      * @param conn TODO: DOCUMENT ME!
222      * @param intransaction TODO: DOCUMENT ME!
223      *
224      * @return total number of records updated/inserted/deleted
225      *
226      * @throws SQLException TODO: DOCUMENT ME!
227      * @throws DataSetException TODO: DOCUMENT ME!
228      */
229     public int save(Connection conn, boolean intransaction)
230             throws SQLException, DataSetException
231     {
232         int j = 0;
233 
234         for (Enumeration e = records.elements(); e.hasMoreElements();)
235         {
236             Record rec = (Record) e.nextElement();
237             rec.save(conn);
238             j++;
239         }
240 
241         // now go through and remove any records
242         // that were previously marked as a zombie by the
243         // delete process
244         removeDeletedRecords();
245 
246         return j;
247     }
248 
249     /***
250      * Removes any records that are marked as a zombie.
251      *
252      * @throws DataSetException TODO: DOCUMENT ME!
253      */
254     public void removeDeletedRecords()
255             throws DataSetException
256     {
257         for (Enumeration e = records.elements(); e.hasMoreElements();)
258         {
259             Record rec = (Record) e.nextElement();
260 
261             if (rec.isAZombie())
262             {
263                 removeRecord(rec);
264             }
265         }
266     }
267 
268     /***
269      * Sets the value for the SQL portion of the WHERE statement
270      *
271      * @param where TODO: DOCUMENT ME!
272      *
273      * @return instance of self
274      *
275      * @throws DataSetException TODO: DOCUMENT ME!
276      */
277     public TableDataSet where(String where)
278             throws DataSetException
279     {
280         if (where == null)
281         {
282             throw new DataSetException("null not allowed for where clause");
283         }
284 
285         this.where = where;
286 
287         return this;
288     }
289 
290     /***
291      * Gets the value of the SQL portion of WHERE.
292      *
293      * @return string
294      */
295     String getWhere()
296     {
297         return this.where;
298     }
299 
300     /***
301      * Sets the value for the SQL portion of the ORDER statement
302      *
303      * @param order TODO: DOCUMENT ME!
304      *
305      * @return instance of self
306      *
307      * @throws DataSetException TODO: DOCUMENT ME!
308      */
309     public TableDataSet order(String order)
310             throws DataSetException
311     {
312         if (order == null)
313         {
314             throw new DataSetException("null not allowed for order clause");
315         }
316 
317         this.order = order;
318 
319         return this;
320     }
321 
322     /***
323      * Gets the value of the SQL portion of ORDER.
324      *
325      * @return string
326      */
327     String getOrder()
328     {
329         return this.order;
330     }
331 
332     /***
333      * Sets the value for the SQL portion of the OTHER statement
334      *
335      * @param other TODO: DOCUMENT ME!
336      *
337      * @return instance of self
338      *
339      * @throws DataSetException TODO: DOCUMENT ME!
340      */
341     public TableDataSet other(String other)
342             throws DataSetException
343     {
344         if (other == null)
345         {
346             throw new DataSetException("null not allowed for other clause");
347         }
348 
349         this.other = other;
350 
351         return this;
352     }
353 
354     /***
355      * Gets the value of the SQL portion of OTHER.
356      *
357      * @return string
358      */
359     String getOther()
360     {
361         return this.other;
362     }
363 
364     /***
365      * This method refreshes all of the Records stored in this TableDataSet.
366      *
367      * @param conn TODO: DOCUMENT ME!
368      *
369      * @throws SQLException TODO: DOCUMENT ME!
370      * @throws DataSetException TODO: DOCUMENT ME!
371      */
372     public void refresh(Connection conn)
373             throws SQLException, DataSetException
374     {
375         for (Enumeration e = records.elements(); e.hasMoreElements();)
376         {
377             Record rec = (Record) e.nextElement();
378             rec.refresh(conn);
379         }
380     }
381 
382     /***
383      * Setting this causes each Record to refresh itself when a save() is performed on it.
384      *
385      * <P>
386      * Default value is false.
387      * </p>
388      *
389      * @param val TODO: DOCUMENT ME!
390      */
391     public void setRefreshOnSave(boolean val)
392     {
393         this.refreshOnSave = val;
394     }
395 
396     /***
397      * Setting this causes each Record to refresh itself when a save() is performed on it.
398      *
399      * <P>
400      * Default value is false.
401      * </p>
402      *
403      * @return true if it is on; false otherwise
404      */
405     public boolean refreshOnSave()
406     {
407         return this.refreshOnSave;
408     }
409 
410     /***
411      * This sets additional SQL for the table name. The string appears after the table name. Sybase users would set this to
412      * "HOLDLOCK" to get repeatable reads.
413      *
414      * <P>
415      * FIXME: Is this right? I don't use Sybase.
416      * </p>
417      *
418      * @param tq TODO: DOCUMENT ME!
419      *
420      * @return an instance of self
421      */
422     public TableDataSet tableQualifier(String tq)
423     {
424         // go directly to schema() cause it is where tableName is stored
425         schema().appendTableName(tq);
426 
427         return this;
428     }
429 
430     /***
431      * Builds the select string that was used to populate this TableDataSet.
432      *
433      * @return SQL select string
434      *
435      * @throws DataSetException TODO: DOCUMENT ME!
436      */
437     public String getSelectString()
438             throws DataSetException
439     {
440         buildSelectString();
441 
442         return this.selectString.toString();
443     }
444 
445     /***
446      * Used by getSelectString to build the select string that was used to populate this TableDataSet.
447      *
448      * @throws DataSetException TODO: DOCUMENT ME!
449      */
450     private void buildSelectString()
451             throws DataSetException
452     {
453         if (selectString == null)
454         {
455             selectString = new StringBuffer(256);
456         }
457         else
458         {
459             selectString.setLength(0);
460         }
461 
462         selectString.append("SELECT ");
463         selectString.append(schema().attributes());
464         selectString.append(" FROM ");
465         selectString.append(schema().tableName());
466 
467         if ((this.where != null) && (this.where.length() > 0))
468         {
469             selectString.append(" WHERE " + this.where);
470         }
471 
472         if ((this.order != null) && (this.order.length() > 0))
473         {
474             selectString.append(" ORDER BY " + this.order);
475         }
476 
477         if ((this.other != null) && (this.other.length() > 0))
478         {
479             selectString.append(this.other);
480         }
481     }
482 }