1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package com.finalist.jaggenerator;
19
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Collections;
27 import java.sql.Connection;
28 import java.sql.ResultSet;
29 import java.sql.SQLException;
30 import java.sql.DatabaseMetaData;
31
32 /***
33 * This class is a refactoring mid-step. The original code contained duplicate methods for database access
34 * in different classes - I've rehoused them here.
35 *
36 * @author Michael O'Connor, Rudie Ekkelenkamp - Finalist IT Group
37 */
38 public class DatabaseUtils {
39 static Log log = LogFactory.getLog(DatabaseUtils.class);
40
41
42 private static final HashMap columnsCache = new HashMap();
43
44
45 private static ArrayList tablesCache;
46
47
48 private static final HashMap pkCache = new HashMap();
49 private static final String TABLE_NAME = "TABLE_NAME";
50 private static final String[] DEFAULT_TABLE_TYPES = new String[]{"TABLE"};
51
52
53 /***
54 * Gets all columns in the specified table, setting up a database connection if one isn't already available.
55 *
56 * @param tablename the name of the table.
57 * @return an ArrayList of Column objects for all columns in the specified table,
58 * or <code>null</code> if the table/column doesn't exist.
59 */
60 public static ArrayList getColumns(String tablename) {
61 return getColumns(tablename, true);
62 }
63
64 /***
65 * Gets all columns in the specified table.
66 *
67 * @param tablename the name of the table.
68 * @param forceConnection set to <code>true</code> if this method should force a database connect,
69 * if not already connected.
70 * @return an ArrayList of Column objects for all columns in the specified table;
71 * or <code>null</code> if the table/column doesn't exist, or if no database connection was available and
72 * <code>forceConnection</code> was set to <code>false</code>.
73 */
74 public static ArrayList getColumns(String tablename, boolean forceConnection) {
75 if (columnsCache.get(tablename) != null) {
76 return (ArrayList) columnsCache.get(tablename);
77 }
78
79 if (!forceConnection && JagGenerator.getConManager() == null) {
80 return null;
81 }
82 ArrayList pkeys = getPrimaryKeys(tablename);
83 GenericJdbcManager conManager = JagGenerator.getConManager();
84 Connection con = null;
85 ArrayList list = new ArrayList();
86 try {
87 con = conManager.connect();
88 DatabaseMetaData meta = con.getMetaData();
89 ResultSet columns = meta.getColumns(null, conManager.getSchema(), tablename, "%");
90 Column c = null;
91 while (columns.next()) {
92 c = new Column();
93 switch (columns.getInt("NULLABLE")) {
94 case DatabaseMetaData.columnNullable:
95 c.setNullable(true);
96 break;
97 case DatabaseMetaData.columnNoNulls:
98 c.setNullable(false);
99 break;
100 case DatabaseMetaData.columnNullableUnknown:
101 c.setNullable(false);
102 default:
103 c.setNullable(true);
104 }
105
106 c.setName(columns.getString("COLUMN_NAME"));
107 if (pkeys.contains(columns.getString("COLUMN_NAME"))) {
108 c.setPrimaryKey(true);
109 } else {
110 c.setPrimaryKey(false);
111 }
112
113 c.setLength(columns.getInt("COLUMN_SIZE"));
114 c.setPrecision(columns.getInt("COLUMN_SIZE"));
115 c.setScale(columns.getInt("DECIMAL_DIGITS"));
116 c.setSqlType(columns.getString("TYPE_NAME"));
117 list.add(c);
118 }
119 columns.close();
120
121 } catch (Exception e) {
122 e.printStackTrace();
123 } finally {
124 if (con != null) {
125 try {
126 con.close();
127 } catch (SQLException e) {
128 }
129 }
130 }
131
132 columnsCache.put(tablename, list);
133 return list;
134 }
135
136 /***
137 * Gets information about any foreign keys that are imported into the specified table.
138 *
139 * @param tablename
140 * @return a List of ForeignKey objects, never <code>null</code>..
141 */
142 public static List getForeignKeys(String tablename) {
143 log.debug("Get the foreign keys for table: " + tablename);
144 ArrayList fkeys = new ArrayList();
145 GenericJdbcManager conManager = JagGenerator.getConManager();
146 if (conManager == null) {
147 JagGenerator.logToConsole("Can't retrieve foreign keys - no database connection!");
148 } else {
149 Connection con = null;
150 try {
151 con = conManager.connect();
152 ResultSet foreignKeys = con.getMetaData().getImportedKeys("", conManager.getSchema(), tablename);
153
154 while (foreignKeys.next()) {
155 ForeignKey fk = new ForeignKey();
156 try {
157 fk.setPkTableCat(foreignKeys.getString("PKTABLE_CAT"));
158 } catch (Exception e) {
159
160 }
161 try {
162 fk.setPkTableSchem(foreignKeys.getString("PKTABLE_SCHEM"));
163 } catch (Exception e) {
164
165 }
166 try {
167 fk.setPkTableName(foreignKeys.getString("PKTABLE_NAME"));
168 } catch (Exception e) {
169
170 }
171 try {
172
173 fk.setPkColumnName(foreignKeys.getString("PKCOLUMN_NAME"));
174 } catch (Exception e) {
175
176 }
177 try {
178 fk.setFkTableCat(foreignKeys.getString("FKTABLE_CAT"));
179 } catch (Exception e) {
180
181 }
182 try {
183
184 fk.setFkTableSchem(foreignKeys.getString("FKTABLE_SCHEM"));
185 } catch (Exception e) {
186
187 }
188 try {
189
190 fk.setFkTableName(foreignKeys.getString("FKTABLE_NAME"));
191 } catch (Exception e) {
192
193 }
194 try {
195
196 fk.setFkColumnName(foreignKeys.getString("FKCOLUMN_NAME"));
197 } catch (Exception e) {
198
199 }
200 try {
201
202 fk.setKeySeq(foreignKeys.getShort("KEY_SEQ"));
203 } catch (Exception e) {
204
205 }
206 try {
207 fk.setUpdateRule(foreignKeys.getShort("UPDATE_RULE"));
208 } catch (Exception e) {
209
210 }
211 try {
212
213 fk.setDeleteRule(foreignKeys.getShort("DELETE_RULE"));
214 } catch (Exception e) {
215
216 }
217 try {
218
219 fk.setPkName(foreignKeys.getString("PK_NAME"));
220 } catch (Exception e) {
221
222 }
223 try {
224
225 fk.setDeferrability(foreignKeys.getShort("DEFERRABILITY"));
226 } catch (Exception e) {
227
228 }
229
230 log.debug("Foreign key table and column name: " + fk.getFkTableName() + " - " + fk.getFkColumnName());
231 log.debug("foreign table and pk column name: " + fk.getPkTableName() + " - " + fk.getPkColumnName());
232
233
234 fk.setFkName(Utils.format(fk.getFkColumnName()));
235 fkeys.add(fk);
236 }
237 } catch (Exception e) {
238 e.printStackTrace();
239 } finally {
240 if (con != null) {
241 try {
242 con.close();
243 } catch (SQLException e) {
244 }
245 }
246 }
247 }
248
249 return fkeys;
250 }
251
252 /***
253 * A list with Strings of all primary key fields.
254 *
255 * @param tablename
256 * @return an ArrayList of primary key column names for the specified table, never <code>null</code>.
257 * @todo make this private - all primary key work should be done in this class.
258 */
259 public static ArrayList getPrimaryKeys(String tablename) {
260 if (pkCache.get(tablename) != null) {
261 return (ArrayList) pkCache.get(tablename);
262 }
263 GenericJdbcManager conManager = JagGenerator.getConManager();
264 Connection con = null;
265 ArrayList pkeys = new ArrayList();
266 try {
267 con = conManager.connect();
268 ResultSet r = con.getMetaData().getPrimaryKeys(null, conManager.getSchema(), tablename);
269 while (r.next()) {
270 pkeys.add(r.getString("COLUMN_NAME"));
271 }
272 } catch (Exception e) {
273 e.printStackTrace();
274 } finally {
275 if (con != null) {
276 try {
277 con.close();
278 } catch (SQLException e) {
279 }
280 }
281 }
282
283 pkCache.put(tablename, pkeys);
284 return pkeys;
285 }
286
287 /***
288 * Grabs the list of tables from the database.
289 *
290 * @return a List of table names (String), never <code>null</code>.
291 */
292 public static ArrayList getTables() {
293 if (tablesCache == null) {
294 tablesCache = new ArrayList();
295 GenericJdbcManager conManager = JagGenerator.getConManager();
296 String[] displayTableTypes = conManager.getDisplayTableTypes();
297 if (displayTableTypes == null) {
298 displayTableTypes = DEFAULT_TABLE_TYPES;
299 }
300 ResultSet tables = null;
301 Connection con = null;
302 try {
303 con = conManager.connect();
304
305 ResultSet schemas = con.getMetaData().getSchemas();
306 while (schemas.next()) {
307 Object o = schemas.getObject(1);
308 System.out.println("schema:" + o);
309 }
310
311 tables = con.getMetaData().getTables(null, conManager.getSchema(), "%", displayTableTypes);
312
313 while (tables.next()) {
314
315 String tableName = tables.getString(TABLE_NAME);
316 if (tableName != null) {
317 tablesCache.add(tableName);
318 }
319 }
320 } catch (Exception e) {
321 e.printStackTrace();
322 JagGenerator.logToConsole("Error getting tables list: " + e.toString());
323
324 } finally {
325
326 if (tables != null)
327 try {
328 tables.close();
329 } catch (Exception e) {
330 }
331
332 if (con != null)
333 try {
334 con.close();
335 } catch (SQLException e) {
336 }
337 }
338 }
339 if (tablesCache != null)
340 Collections.sort(tablesCache);
341 return tablesCache;
342 }
343
344 /***
345 * This needs to be called when databases are switched.
346 */
347 public static void clearCache() {
348 tablesCache = null;
349 }
350
351 /***
352 * Forces an update of a particular table's columns the next time they are required.
353 *
354 * @param tableName
355 */
356 public static void clearColumnsCacheForTable(String tableName) {
357 columnsCache.remove(tableName);
358 }
359
360 }