1
2 package net.sourceforge.jdbdump.dump;
3
4 import java.io.IOException;
5 import java.io.ObjectInputStream;
6 import java.io.Serializable;
7 import java.sql.SQLException;
8 import java.util.Vector;
9
10 import org.apache.log4j.Logger;
11
12 /***
13 * Represents a table in a database. Objects of this class should be created either by a
14 * DatabaseConnector during the execution of dump() method, or by a DumpFileManager
15 * while recreating a Dump from a saved backup file.
16 * A table must have its name assigned, and should also have a number of columns (handled by
17 * Column class). Optionally a table can also have one or more Triggers.
18 * <br /><br />
19 * Table is different from other classes in this package in that it is the only one which
20 * has the ability to download more information from the database after the Dump structure
21 * is created. This is done to let a DumpFileManager download parts of data and immediately
22 * store them in a file (or, in the same way, load data from a file and insert them into
23 * database). Otherwise the entire contents of a database (often many megabytes or even
24 * gigabytes) would have to be kept in memory.
25 * <br /><br />
26 * Database data is loaded using methods initializeData() and getDataLine(). The former is
27 * executed once per table to prepare the data stream, and the latter is called for each
28 * record of data. Data can be saved to a dump file just after they are downloaded, so
29 * only one record occupies the memory at the same time.
30 * <br /><br />
31 * Example code:
32 * <pre>
33 * DatabaseConnectorFactory factory = DatabaseConnectorFactory.getInstance();
34 * if (connectorTypes.length > 0) {
35 * DatabaseConnector connector = factory.createConnector(
36 * "net.sourceforge.jdbdump.connect.connectors.MysqlConnector");
37 * connector.connect("jdbc:mysql://localhost/base", "admin", "qwerty");
38 * Dump dump = connector.dump();
39 * File dumpFile = new File("dump.bin");
40 * // ...write the structure to a file...
41 * for (Table t : dump.getTables()) {
42 * t.initializeData();
43 * while (true) {
44 * String record[] = t.getDataLine();
45 * if (record == null) break;
46 * // ...write one line with an insert command...
47 * }
48 * }
49 * connector.disconnect();
50 * } else {
51 * // error - no connectors
52 * }
53 * </pre>
54 *
55 * @author jsuder
56 */
57
58 public class Table implements Serializable {
59
60 /*** ID used in serialization process. */
61 private static final long serialVersionUID = -5780410768401074139L;
62
63 /*** Name of the table. */
64 private String name;
65
66 /*** A list of table's columns. */
67 private Vector<Column> columns;
68
69 /*** A list of table's constraints (primary/foreign keys, etc.). */
70 private Vector<Constraint> constraints;
71
72 /*** A log4j logger for this class. */
73 private static Logger logger = Logger.getLogger(Table.class);
74
75 /*** A reference to a Dump object in which this Table is contained. */
76 private transient Dump dump;
77
78 /*** Tells if initializeData() and getDataLine() methods should operate on a database,
79 * or a backup file. */
80 private transient boolean readFromDatabase;
81
82
83 /***
84 * Creates a new table with specified name.
85 * @param name table's name
86 * @param connection database connection which will be used to dump table's data
87 */
88
89 public Table(String name, Dump dump) {
90 this.name = name;
91 this.dump = dump;
92 columns = new Vector<Column>();
93 constraints = new Vector<Constraint>();
94 }
95
96 /***
97 * Sets a reference to a Dump object which contains this Table.
98 * @param dump a database dump
99 */
100
101 public void setDump(Dump dump) {
102 this.dump = dump;
103 }
104
105 /***
106 * Returns table's name.
107 * @return table's name
108 */
109
110 public String getName() {
111 return name;
112 }
113
114 /***
115 * Sets table's name.
116 * @return table's new name
117 */
118
119 public void setName(String name) {
120 this.name = name;
121 }
122
123 /***
124 * Returns a list of this table's constraints (including primary and foreign keys).
125 * @return a list of table's constraints
126 */
127
128 public Vector<Constraint> getConstraints() {
129 return constraints;
130 }
131
132 /***
133 * Adds a new constraint to this table.
134 * @param constraint a constraint to be added to the list
135 */
136
137 public void addConstraint(Constraint constraint) {
138 constraints.add(constraint);
139 }
140
141 /***
142 * Prepares table's data for downloading using getDataLine().
143 * @throws SQLException if data download can't be initialized because of a connection
144 * error or an error in the database
145 */
146
147 public void initializeData() throws SQLException {
148 readFromDatabase = dump.isReadingFromDatabase();
149 if (readFromDatabase) {
150 dump.getDatabaseReader().initializeTableData(name);
151 logger.info("initializeData(): data from table " + name + " is ready for downloading.");
152 } else {
153
154 }
155 }
156
157 /***
158 * Downloads one record of data from this table in database or from a file (depending
159 * on the value of readFromDatabase attribute).
160 * @return next record from the table, or null if there are no more records
161 * @throws Exception if data record can't be downloaded because of a connection error
162 * or an error in the database, or because of an IO error during the reading from
163 * a backup file
164 */
165
166 public String[] getDataLine() throws Exception {
167 if (readFromDatabase) {
168 return getDataLineFromDatabase();
169 } else {
170 return getDataLineFromFile();
171 }
172 }
173
174 /***
175 * Downloads one record of data from this table in database.
176 * @return next record from the table, or null if there are no more records
177 * @throws SQLException if data record can't be downloaded because of a connection error
178 * or an error in the database
179 */
180
181 public String[] getDataLineFromDatabase() throws SQLException {
182 return dump.getDatabaseReader().getTableDataLine();
183 }
184
185 /***
186 * Reads one record of data from a backup file.
187 * @return next record from the table, or null if there are no more records
188 * @throws IOException if data can't be read from the file
189 * @throws ClassNotFoundException if the read object doesn't match the required class
190 */
191
192 public String[] getDataLineFromFile() throws IOException, ClassNotFoundException {
193 String[] dataLine = (String[]) dump.getFileReader().readObject();
194 return dataLine;
195 }
196
197 /***
198 * Returns number of columns in the table.
199 * @return number of columns in the table
200 */
201
202 public Vector<Column> getColumns() {
203 return columns;
204 }
205
206 /***
207 * Reads an object from a file using serialization and initializes it.
208 * @param in an input stream from which the object will be read
209 * @throws IOException if the object can't be read from the file
210 * @throws ClassNotFoundException if the saved object format doesn't match this class
211 */
212
213 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
214 in.defaultReadObject();
215 this.dump = null;
216 this.readFromDatabase = false;
217 }
218 }