1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 package com.workingdogs.village;
54
55 import java.sql.Connection;
56 import java.sql.ResultSet;
57 import java.sql.SQLException;
58
59 import java.util.Enumeration;
60
61 /***
62 * This class is used for doing select/insert/delete/update on the database. A TableDataSet cannot be used to join multiple tables
63 * for an update, if you need join functionality on a select, you should use a <a href="QueryDataSet.html">QueryDataSet</a>.
64 *
65 * <P>
66 * Here is an example usage for this code that gets the first 10 records where column "a" = 1:
67 * <PRE>
68 * KeyDef kd = new KeyDef().setAttrib("column");
69 * TableDataSet tds = new TableDataSet(connection, "table_name", kd );
70 * tds.where ("a=1" ); // WHERE a = 1
71 * tds.fetchRecords(10); // fetch first 10 records where column a=1
72 * for ( int i=0;i< tds.size(); i++ )
73 * {
74 * Record rec = tds.getRecord(i); // zero based
75 * String columnA = rec.getValue("a");
76 * if ( columnA.equals ("1") )
77 * System.out.print ("We got a column!");
78 * }
79 * tds.close();
80 * </PRE>
81 * </p>
82 *
83 * <P>
84 * It is important to remember to always close() the TableDataSet when you are finished with it.
85 * </p>
86 *
87 * <P>
88 * As you can see, using a TableDataSet makes doing selects from the database trivial. You do not need to write any SQL and it
89 * makes it easy to cache a TableDataSet for future use within your application.
90 * </p>
91 *
92 * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
93 * @version $Revision: 568 $
94 */
95 public class TableDataSet
96 extends DataSet
97 {
98 /*** the optimistic locking column value */
99 private String optimisticLockingCol;
100
101 /*** the value for the sql where clause */
102 private String where = null;
103
104 /*** the value for the sql order by clause */
105 private String order = null;
106
107 /*** the value for the sql other clause */
108 private String other = null;
109
110
111
112 /*** TODO: DOCUMENT ME! */
113 private boolean refreshOnSave = false;
114
115 /***
116 * Default constructor.
117 *
118 * @exception SQLException
119 * @exception DataSetException
120 */
121 public TableDataSet()
122 throws SQLException, DataSetException
123 {
124 super();
125 }
126
127 /***
128 * Creates a new TableDataSet object.
129 *
130 * @param conn TODO: DOCUMENT ME!
131 * @param tableName TODO: DOCUMENT ME!
132 *
133 * @throws SQLException TODO: DOCUMENT ME!
134 * @throws DataSetException TODO: DOCUMENT ME!
135 */
136 public TableDataSet(Connection conn, String tableName)
137 throws SQLException, DataSetException
138 {
139 super(conn, tableName);
140 }
141
142 /***
143 * Creates a new TableDataSet object.
144 *
145 * @param conn TODO: DOCUMENT ME!
146 * @param schema TODO: DOCUMENT ME!
147 * @param keydef TODO: DOCUMENT ME!
148 *
149 * @throws SQLException TODO: DOCUMENT ME!
150 * @throws DataSetException TODO: DOCUMENT ME!
151 */
152 public TableDataSet(Connection conn, Schema schema, KeyDef keydef)
153 throws SQLException, DataSetException
154 {
155 super(conn, schema, keydef);
156 }
157
158 /***
159 * Creates a new TableDataSet object.
160 *
161 * @param conn TODO: DOCUMENT ME!
162 * @param tableName TODO: DOCUMENT ME!
163 * @param keydef TODO: DOCUMENT ME!
164 *
165 * @throws SQLException TODO: DOCUMENT ME!
166 * @throws DataSetException TODO: DOCUMENT ME!
167 */
168 public TableDataSet(Connection conn, String tableName, KeyDef keydef)
169 throws SQLException, DataSetException
170 {
171 super(conn, tableName, keydef);
172 }
173
174 /***
175 * Creates a new TableDataSet object.
176 *
177 * @param conn TODO: DOCUMENT ME!
178 * @param tableName TODO: DOCUMENT ME!
179 * @param columns TODO: DOCUMENT ME!
180 *
181 * @throws SQLException TODO: DOCUMENT ME!
182 * @throws DataSetException TODO: DOCUMENT ME!
183 */
184 public TableDataSet(Connection conn, String tableName, String columns)
185 throws SQLException, DataSetException
186 {
187 super(conn, tableName, columns);
188 }
189
190 /***
191 * Creates a new TableDataSet object.
192 *
193 * @param conn TODO: DOCUMENT ME!
194 * @param tableName TODO: DOCUMENT ME!
195 * @param columns TODO: DOCUMENT ME!
196 * @param keydef TODO: DOCUMENT ME!
197 *
198 * @throws SQLException TODO: DOCUMENT ME!
199 * @throws DataSetException TODO: DOCUMENT ME!
200 */
201 public TableDataSet(Connection conn, String tableName, String columns, KeyDef keydef)
202 throws SQLException, DataSetException
203 {
204 super(conn, tableName, columns, keydef);
205 }
206
207 /***
208 * Use the TDS fetchRecords instead of the DataSet.fetchRecords
209 *
210 * @return an instance of myself
211 *
212 * @exception SQLException
213 * @exception DataSetException
214 */
215 public DataSet fetchRecords()
216 throws SQLException, DataSetException
217 {
218 return fetchRecords(-1);
219 }
220
221 /***
222 * Use the TDS fetchRecords instead of the DataSet.fetchRecords
223 *
224 * @param max
225 *
226 * @return an instance of myself
227 *
228 * @exception SQLException
229 * @exception DataSetException
230 */
231 public DataSet fetchRecords(int max)
232 throws SQLException, DataSetException
233 {
234 return fetchRecords(0, max);
235 }
236
237 /***
238 * Fetch start to max records. start is at Record 0
239 *
240 * @param start
241 * @param max
242 *
243 * @return an instance of myself
244 *
245 * @exception SQLException
246 * @exception DataSetException
247 */
248 public DataSet fetchRecords(int start, int max)
249 throws SQLException, DataSetException
250 {
251 buildSelectString();
252
253 return super.fetchRecords(start, max);
254 }
255
256 /***
257 * this is a string that contains the columns for the table that this TableDataSet represents.
258 *
259 * @return columns separated by ","
260 */
261 public String attributes()
262 {
263 return super.getColumns();
264 }
265
266 /***
267 * Returns the KeyDef for the DataSet
268 *
269 * @return a keydef
270 */
271 public KeyDef keydef()
272 {
273 return super.keydef();
274 }
275
276 /***
277 * Returns the ResultSet for the DataSet
278 *
279 * @return a ResultSet
280 *
281 * @throws SQLException TODO: DOCUMENT ME!
282 * @throws DataSetException TODO: DOCUMENT ME!
283 */
284 public ResultSet resultSet()
285 throws SQLException, DataSetException
286 {
287 return super.resultSet();
288 }
289
290 /***
291 * Returns the Schema for the DataSet
292 *
293 * @return a Schema
294 */
295 public Schema schema()
296 {
297 return super.schema();
298 }
299
300 /***
301 * Saves all the records in the DataSet.
302 *
303 * @return total number of records updated/inserted/deleted
304 *
305 * @throws SQLException TODO: DOCUMENT ME!
306 * @throws DataSetException TODO: DOCUMENT ME!
307 */
308 public int save()
309 throws SQLException, DataSetException
310 {
311 return save(connection(), false);
312 }
313
314 /***
315 * Saves all the records in the DataSet with the intransaction boolean value.
316 *
317 * @param intransaction TODO: DOCUMENT ME!
318 *
319 * @return total number of records updated/inserted/deleted
320 *
321 * @throws SQLException TODO: DOCUMENT ME!
322 * @throws DataSetException TODO: DOCUMENT ME!
323 */
324 public int save(boolean intransaction)
325 throws SQLException, DataSetException
326 {
327 return save(connection(), intransaction);
328 }
329
330 /***
331 * Saves all the records in the DataSet with the given connection and intransaction boolean value.
332 *
333 * @param conn TODO: DOCUMENT ME!
334 * @param intransaction TODO: DOCUMENT ME!
335 *
336 * @return total number of records updated/inserted/deleted
337 *
338 * @throws SQLException TODO: DOCUMENT ME!
339 * @throws DataSetException TODO: DOCUMENT ME!
340 */
341 public int save(Connection conn, boolean intransaction)
342 throws SQLException, DataSetException
343 {
344 int j = 0;
345
346 for (Enumeration e = records.elements(); e.hasMoreElements();)
347 {
348 Record rec = (Record) e.nextElement();
349 rec.save(conn);
350 j++;
351 }
352
353
354
355
356 removeDeletedRecords();
357
358 return j;
359 }
360
361 /***
362 * Not yet implemented
363 *
364 * @param conn TODO: DOCUMENT ME!
365 *
366 * @return TODO: DOCUMENT ME!
367 *
368 * @throws SQLException TODO: DOCUMENT ME!
369 * @throws DataSetException TODO: DOCUMENT ME!
370 */
371 public int saveWithoutStatusUpdate(Connection conn)
372 throws SQLException, DataSetException
373 {
374 throw new DataSetException("Not yet implemented!");
375 }
376
377 /***
378 * Hell if I know what this does.
379 *
380 * @return TODO: DOCUMENT ME!
381 */
382 public String debugInfo()
383 {
384 return "Not yet implemented!";
385 }
386
387 /***
388 * Removes any records that are marked as a zombie.
389 *
390 * @throws DataSetException TODO: DOCUMENT ME!
391 */
392 public void removeDeletedRecords()
393 throws DataSetException
394 {
395 for (Enumeration e = records.elements(); e.hasMoreElements();)
396 {
397 Record rec = (Record) e.nextElement();
398
399 if (rec.isAZombie())
400 {
401 removeRecord(rec);
402 }
403 }
404 }
405
406 /***
407 * Sets the table column used for optomistic locking.
408 *
409 * @param olc TODO: DOCUMENT ME!
410 */
411 public void setOptimisticLockingColumn(String olc)
412 {
413 this.optimisticLockingCol = olc;
414 }
415
416 /***
417 * Gets the table column used for optomistic locking.
418 *
419 * @return string
420 */
421 public String optimisticLockingCol()
422 {
423 return this.optimisticLockingCol;
424 }
425
426 /***
427 * Sets the value for the SQL portion of the WHERE statement
428 *
429 * @param where TODO: DOCUMENT ME!
430 *
431 * @return instance of self
432 *
433 * @throws DataSetException TODO: DOCUMENT ME!
434 */
435 public TableDataSet where(String where)
436 throws DataSetException
437 {
438 if (where == null)
439 {
440 throw new DataSetException("null not allowed for where clause");
441 }
442
443 this.where = where;
444
445 return this;
446 }
447
448 /***
449 * Gets the value of the SQL portion of WHERE.
450 *
451 * @return string
452 */
453 String getWhere()
454 {
455 return this.where;
456 }
457
458 /***
459 * Sets the value for the SQL portion of the ORDER statement
460 *
461 * @param order TODO: DOCUMENT ME!
462 *
463 * @return instance of self
464 *
465 * @throws DataSetException TODO: DOCUMENT ME!
466 */
467 public TableDataSet order(String order)
468 throws DataSetException
469 {
470 if (order == null)
471 {
472 throw new DataSetException("null not allowed for order clause");
473 }
474
475 this.order = order;
476
477 return this;
478 }
479
480 /***
481 * Gets the value of the SQL portion of ORDER.
482 *
483 * @return string
484 */
485 String getOrder()
486 {
487 return this.order;
488 }
489
490 /***
491 * Sets the value for the SQL portion of the OTHER statement
492 *
493 * @param other TODO: DOCUMENT ME!
494 *
495 * @return instance of self
496 *
497 * @throws DataSetException TODO: DOCUMENT ME!
498 */
499 public TableDataSet other(String other)
500 throws DataSetException
501 {
502 if (other == null)
503 {
504 throw new DataSetException("null not allowed for other clause");
505 }
506
507 this.other = other;
508
509 return this;
510 }
511
512 /***
513 * Gets the value of the SQL portion of OTHER.
514 *
515 * @return string
516 */
517 String getOther()
518 {
519 return this.other;
520 }
521
522 /***
523 * This method refreshes all of the Records stored in this TableDataSet.
524 *
525 * @param conn TODO: DOCUMENT ME!
526 *
527 * @throws SQLException TODO: DOCUMENT ME!
528 * @throws DataSetException TODO: DOCUMENT ME!
529 */
530 public void refresh(Connection conn)
531 throws SQLException, DataSetException
532 {
533 for (Enumeration e = records.elements(); e.hasMoreElements();)
534 {
535 Record rec = (Record) e.nextElement();
536 rec.refresh(conn);
537 }
538 }
539
540 /***
541 * Setting this causes each Record to refresh itself when a save() is performed on it.
542 *
543 * <P>
544 * Default value is false.
545 * </p>
546 *
547 * @param val TODO: DOCUMENT ME!
548 */
549 public void setRefreshOnSave(boolean val)
550 {
551 this.refreshOnSave = val;
552 }
553
554 /***
555 * Setting this causes each Record to refresh itself when a save() is performed on it.
556 *
557 * <P>
558 * Default value is false.
559 * </p>
560 *
561 * @return true if it is on; false otherwise
562 */
563 public boolean refreshOnSave()
564 {
565 return this.refreshOnSave;
566 }
567
568 /***
569 * This sets additional SQL for the table name. The string appears after the table name. Sybase users would set this to
570 * "HOLDLOCK" to get repeatable reads.
571 *
572 * <P>
573 * FIXME: Is this right? I don't use Sybase.
574 * </p>
575 *
576 * @param tq TODO: DOCUMENT ME!
577 *
578 * @return an instance of self
579 */
580 public TableDataSet tableQualifier(String tq)
581 {
582
583 schema().appendTableName(tq);
584
585 return this;
586 }
587
588 /***
589 * The name of the table for which this TableDataSet was created.
590 *
591 * @return string
592 *
593 * @throws DataSetException TODO: DOCUMENT ME!
594 */
595 public String tableName()
596 throws DataSetException
597 {
598 return super.tableName();
599 }
600
601 /***
602 * Not yet implemented
603 *
604 * @exception SQLException
605 * @exception DataSetException
606 */
607 public void updateStatus()
608 throws SQLException, DataSetException
609 {
610 throw new DataSetException("Not yet implemented!");
611 }
612
613 /***
614 * Builds the select string that was used to populate this TableDataSet.
615 *
616 * @return SQL select string
617 *
618 * @throws DataSetException TODO: DOCUMENT ME!
619 */
620 public String getSelectString()
621 throws DataSetException
622 {
623 buildSelectString();
624
625 return this.selectString.toString();
626 }
627
628 /***
629 * Used by getSelectString to build the select string that was used to populate this TableDataSet.
630 *
631 * @throws DataSetException TODO: DOCUMENT ME!
632 */
633 private void buildSelectString()
634 throws DataSetException
635 {
636 if (selectString == null)
637 {
638 selectString = new StringBuffer(256);
639 }
640 else
641 {
642 selectString.setLength(0);
643 }
644
645 selectString.append("SELECT ");
646 selectString.append(schema().attributes());
647 selectString.append(" FROM ");
648 selectString.append(schema().tableName());
649
650 if ((this.where != null) && (this.where.length() > 0))
651 {
652 selectString.append(" WHERE " + this.where);
653 }
654
655 if ((this.order != null) && (this.order.length() > 0))
656 {
657 selectString.append(" ORDER BY " + this.order);
658 }
659
660 if ((this.other != null) && (this.other.length() > 0))
661 {
662 selectString.append(this.other);
663 }
664 }
665 }