Echando código: Obteniendo la metadata de una base de datos en Java



Más de una vez me tocó revizar si podía conectarme a una base de datos después de la instalación; Normalmente estas base de datos eran Open Source (MySQL, PostgreSQL) o comerciales (Oracle, Sybase). Cada una de ellas tiene una herramienta nativa que permite ejecutar SQL desde la línea de comando.

Por ejemplo, para PostgreSQL usted puede utilizar el comand ‘psql‘:

psql -U postgres -d template1 -h 127.0.0.1

Y para Sybase puede utilizar el comando ‘isql:’

isql -U sa -P -S localhost -D tempdb

¿No tienen nada que ver, verdad?. Bueno, viene Java al rescate. Java cuenta con un API estandar para conectarse a base de datos llamada ‘JDBC‘. JDBC ofrece métodos consistentes sin importar el tipo de base de datos, lo cual hace la programación mucho más fácil.

¿Y que tipo de información podemos obtener con el API de JDBC acerca de la base de datos? Bueno, esa parte si es dependiente del driver (manejador) particular con el que nos conectamos a la base de datos; Si un método no es soportado entonces lo más seguro es que Java arroja una ‘MethodNotImplementedException‘, asique es bueno revizar el manual del vendedor antes de utilizarlo para evitar sorpresas.

Este no es un tutorial completo de JDBC, pero si le voy a mostrar el código de un programa que escribí hace tiempo para probar instalaciones nuevas de BD; No es perfecto pero le dará una idea de todo lo que se puede hacer. El ejemplo está corriendo contra una base de datos Sybase 12.5.1 en Linux:

   1:import java.sql.Connection;

2:import java.sql.DatabaseMetaData;
3:import java.sql.DriverManager;
4:import java.sql.ResultSet;
5:import java.sql.SQLException;
6:import java.util.ResourceBundle;
7:
8:/**
9: * This program performs metadata tests on a given database.
10: * License: LGPL
11: * @author Jose Vicente Nunez Zuleta (josevnz@yahoo.com)
12: * @version 0.1 - 05/06/2003
13: */
14:public class TestJDBC {
15:
16: /**
17: * Command line processing
18: * @param args Currently ignored
19: * @throws Exception If any of the required properties is missing
20: */
21: public static void main(String [] args) throws Exception {
22: Connection con = null;
23: ResultSet result = null;
24: ResultSet result2 = null;
25: DatabaseMetaData metadata = null;
26: try {
27: // Connect to the database
28: ResourceBundle bundle = ResourceBundle.getBundle("TestJDBC");
29: System.out.println("Using driver: " + bundle.getString("driver"));
30: Class.forName(bundle.getString("driver")).newInstance();
31: System.out.println("Requesting connection using: user='" +
bundle.getString("user") +
"', password='" + bundle.getString("password") + "', url='" +
bundle.getString("url") + "'");
32: con = DriverManager.getConnection(bundle.getString("url"),
bundle.getString("user"), bundle.getString("password"));
33: System.out.println("Got connection");
34:
35: // Retrieve the database metadata information
36: metadata = con.getMetaData();
37: result = metadata.getCatalogs();
38: String catalog = null;
39: while(result.next()) {
40: System.out.println("Catalog: " + result.getString(1));
41: catalog = result.getString(1);
42: }
43: result.close();
44: // Get information about a catalog and table if both are defined
45: if ( (bundle.getString("catalog") != null) &&
(bundle.getString("catalog").length() > 0) &&
(bundle.getString("tableName") != null) &&
(bundle.getString("tableName").length() > 0)) {
46: result = metadata.getTables(bundle.getString("catalog"),
null
, bundle.getString("tableName"), null);
47: while(result.next()) {
48: System.out.println("Table name: " +
result.getString("TABLE_NAME"));
49: }
50: result.close();
51: System.out.println("Getting the best identifiers for table "
+
bundle.getString("tableName"));
52: result = metadata.getIndexInfo(bundle.getString("catalog"), null,
bundle.getString("tableName"), true, false);
53: while(result.next()) {
54: if (result.getString("INDEX_NAME") != null) {
55: System.out.println("\t\tBest id for the table: "
+
result.getString("COLUMN_NAME"));
56: }
57: }
58: result.close();
59: }
60: if ( (bundle.getString("catalog") != null) &&
(bundle.getString("catalog").length() > 0)
&
& (bundle.getString("procedureName") != null) &&
(bundle.getString("procedureName").length() > 0)) {
61: result = metadata.getProcedureColumns(bundle.getString("catalog"),
null, bundle.getString("procedureName"), null);
62: while(result.next()) {
63: System.out.println("Procedure parameter: " +
result.getString("COLUMN_NAME"));
64: System.out.println("\t\t" +
result.getString("COLUMN_NAME") + " Is there\n");
65: }
66: }
67: } catch (SQLException sqlExp) {
68: System.err.println("Error code #: " + sqlExp.getErrorCode());
69: System.err.println("Error string : " + sqlExp.toString());
70: System.err.println("SQLState: " + sqlExp.getSQLState());
71: sqlExp.printStackTrace();
72: } catch (Exception exp) {
73: exp.printStackTrace();
74: } finally {
75: if (result != null) {
76: try { result.close(); } catch (SQLException ignore) {};
77: }
78: if (result2 != null) {
79: try { result2.close(); } catch (SQLException ignore) {};
80: }
81: if (con != null) {
82: try { con.close(); } catch (SQLException ignore) {}
83: }
84: }
85: }
86:}

Y el archivo de configuracion (ResourceBundle):

   1:user=postgres

2:#user=XXXX
3:#password=XXXX
4:password=
5:url=jdbc:postgresql:dbsrv:5432/template1
6:#url=jdbc:sybase:Tds:dbsrv:4100/tempdb
7:#driver=com.sybase.jdbc2.jdbc.SybDriver
8:driver=org.postgresql.Driver
9:tableName=cmo_details
10:#catalog=SECURITIESDB
11:#procedureName=dealpool_bucket
12:catalog=
13:procedureName=

La salida del programa es como sigue:

[josevnz@god jdbc]$ java TestJDBC

Using driver: com.sybase.jdbc2.jdbc.SybDriver

Requesting connection using: user=’XXXX’, password=’XXXX’, url=’jdbc:sybase:Tds:dbsrv:4100/tempdb’

Got connection

Catalog: MYDB1

Catalog: MYDB2

Catalog: SECURITIESDB

Catalog: master

Catalog: model

Catalog: sybsystemdb

Catalog: sybsystemprocs

Catalog: tempdb

Table name: cmo_details

Getting the best identifiers for table cmo_details

Best id for the table: dealname

Best id for the table: groupnumber

Procedure parameter: RETURN_VALUE

RETURN_VALUE Is there

Procedure parameter: @deal_name

@deal_name Is there

Procedure parameter: @groupnumber

@groupnumber Is there

Procedure parameter: @total_currentbalance

@nb_total_currentbalance Is there

Procedure parameter: @debug_flag

@debug_flag Is there

[josevnz@god jdbc]$

Como siempre, espero haberle despertado su curiosidad 🙂