Omet navegació

6.1 - Accés a les Meta Dades

Normalment quan accedim a una Base de Dades des d'un programa Java, coneixerem l'estructura d'aquesta Base de Dades, és a dir, les taules que té i cada taula quins camps i de quin tipus són. I fins i tot les claus externes entre les taules.

Però podria passar que no coneguérem aquesta estructura. Això no hauria de ser un problema per accedir a la Base de Dades, ja que aquesta és autodescriptiva, és a dir, que hem de poder consultar a la Base de Dades per a que ens diga la seua estructura.

L'objecte que ens dóna aquesta informació és el DatabaseMetaData. Disposa de molts mètodes que ens proporcionen gran quantitat d'informació.

I també ens dóna informació un altre objecte, ResultSetMetaData, que obtindrà la informació a partir d'un ResultSet. Veurem els dos per separat.

DatabaseMetaData

És l'adequat quan volem veure les taules i vistes que tenim en la Base de Dades, així com l'estructura de cadascuna d'elles.

Mirem primer els mètodes més interessants que té:

Valor tornat Nom del mètode Descripció
String getDatabaseProductName()  Torna el nom del SGBD
String getDriverName() Torna el driver JDBC utilitzat
String getURL() Torna la URL de la connexió 
String getUserName() Torna el nom de l'usuari que s'ha connectat 
ResultSet getTables(cataleg, esquema, nom, tipus)  Torna informació de totes les taules que coincideixen amb els patrons o criteris.
Si posem null a tots els paràmetres ens tornarà totes les taules i vistes
ResultSet getColumns(cataleg, esquema, nom, nom_columna)  Torna informació de les columnes de la taula especificada en el tercer paràmetre
(que està en el catàleg i en l'esquema, si els posem).
El quart paràmetre servirà per a seleccionar les columnes  que coincidesquen amb el patró (null per a totes)
ResultSet  getPrimaryKeys(cataleg, esquema, taula) Torna la llista de camps que formen la clau principal 
ResultSet  getImportedKeys(cataleg, esquema, taula)  Torna una llista amb les claus externes definides en aquesta taula 
ResultSet  getExportedKeys(cataleg, esquema, taula)  Torna una llista amb les claus externes que apunten a aquesta taula 

Per poder comprovar tot l'anterior, farem un programa que ens done informació de la Base de Dades, una relació de les taules i vistes que té.

Posteriorment acceptarà un número, i traurà la informació de la taula corresponent amb aquest format: columnes, tipus, clau principal, claus externes.

 Copieu elsegüent codi en un fitxer Kotlin anomenat Exemple_4_31_MetaData.kt:

package exemples

import java.sql.DriverManager
import java.io.BufferedReader
import java.io.InputStreamReader

fun main(args: Array<String>) {
    val con = DriverManager.getConnection ("jdbc:postgresql://89.36.214.106:5432/geo_ad", "geo_ad", "geo_ad")

    val dbmd = con.getMetaData ()
    println("Informació general")
    println("------------------")
    println("SGBD " + dbmd.getDatabaseProductName())
    println("Driver " + dbmd.getDriverName())
    println("URL " + dbmd.getURL())
    println("Usuari " + dbmd.getUserName())
    println()
    println("Llistat de taules")
    println(String.format("%-6s %-7s %-7s %-10s %-10s", "Número", "Catàleg", "Esquema", "Nom", "Tipus"))
    println("---------------------------------------------")
    val ll = dbmd.getTables(null, "public", null, null)
    var compt = 1
    val taules = ArrayList<String>()
    while (ll.next()) {
        println(String.format("%-6d %-7s %-7s %-10s %-10s",(compt++),ll.getString(1),ll.getString(2),ll.getString(3),ll.getString(4)))
        taules.add(ll.getString(3))
    }
    println()
    println("Introdueix un número per veure l'estructura de la taula (0 per acabar) ")
    val ent = BufferedReader(InputStreamReader (System.`in`))
    var opcio = Integer.parseInt(ent.readLine())

    while (opcio != 0) {
        if (opcio < compt && opcio > 0) {
            val taula = dbmd.getTables (null, "public", taules.get(opcio-1), null)
            if (taula.next()) {
                if (taula.getString(4).equals("TABLE")) {
                    val rs = dbmd.getColumns (null, "public", taules.get(opcio-1), null)
                    println("Estructura de la taula " + taules.get(opcio - 1))
                    println("----------------------------")
                    while (rs.next())
                        println(rs.getString(4) + " (" + rs.getString(6) + ")")
                    println("----------------------------")

                    val rs2 = dbmd.getPrimaryKeys(null, "public", taules.get(opcio - 1))
                    print("Clau principal ")
                    while (rs2.next())
                        print(rs2.getString(4) + " ")
                    println()

                    val rs3 = dbmd.getImportedKeys(null, "public", taules.get(opcio - 1))
                    println("Claus externes ")
                    while (rs3.next()) {
                        println(rs3.getString(8) + " apunta a " + rs3.getString(3))
                    }
                    rs.close()
                    rs2.close()
                    rs3.close()
                }
            }
            taula.close()

        }
        println()
        println("Introdueix un número per veure l'estructura de la taula (0 per acabar) ")
        opcio = Integer.parseInt(ent.readLine())
    }
    ll.close()
    con.close()
}

ResultSetMetaData

Una vegada executada una sentència SELECT de SQL que ja tenim el resultat en un ResultSet, podem accedir també a meta dades d'aquest ResultSet, obtenint per exemple el número de columnes, o el tipus de les columnes. Ho obtenim per mig del ResulSetMetaData.

Només veurem 3 mètodes

Valor tornat Nom del mètode Descripció
int getColumnCount()  Torna el número de columnes del ResultSet
String getColumnName(index) Torna el nom de la columna (la primera columna és la 1)
String getColumnTypeName(index) Torna el tipus de la columna 

El següent exemple és una modificació del programa anterior, on ara traurem tot el contingut d'una taula per mig de la sentència SELECT * FROM taula. Intentarem donar-li un aspecte tabular, però sense patir molt per l'aspecte.

Copieu el següent codi en un fitxer Kotlin anomenat Exemple_4_32_ResultSetMetaData.kt :

package exemples

import java.sql.DriverManager
import java.io.BufferedReader
import java.io.InputStreamReader

fun main(args: Array<String>) {
    val con = DriverManager.getConnection("jdbc:postgresql://89.36.214.106:5432/geo_ad", "geo_ad", "geo_ad")

    val dbmd = con.getMetaData()
    println("Llistat de taules:")
    println(String.format("%-6s %-7s %-7s %-10s %-10s", "Número", "Catàleg", "Esquema", "Nom", "Tipus"))
    println("---------------------------------------------")
    val ll = dbmd.getTables(null, "public", null, null)
    var compt = 1
    val taules = ArrayList<String>()
    while (ll.next()) {
        println(String.format("%-6d %-7s %-7s %-10s %-10s",(compt++),ll.getString(1),ll.getString(2),
            ll.getString(3),ll.getString(4)))
        taules.add(ll.getString(3))
    }
    println()
    println("Introdueix un número per veure el contingut de la taula (0 per acabar): ")
    val ent = BufferedReader(InputStreamReader(System.`in`))
    var opcio = Integer.parseInt(ent.readLine())

    while (opcio != 0) {
        if (opcio < compt && opcio > 0) {
            val taula = dbmd.getTables(null, "public", taules.get(opcio - 1), null)
            if (taula.next()) {
                if (taula.getString(4).equals("TABLE")) {
                    val rs = con.createStatement().executeQuery("SELECT * FROM " + taules.get(opcio - 1) + " ORDER BY 1")
                    println("Contingut de la taula " + taules.get(opcio - 1))
                    println("----------------------------")

                    val rsmd = rs.getMetaData()
                    for (i in 1..rsmd.getColumnCount())
                        print(String.format("%-20.20s", rsmd.getColumnName(i)))
                    println()
                    println("------------------------------------------")

                    while (rs.next()) {
                        for (i in 1..rsmd.getColumnCount())
                            print(String.format("%-20.20s ", rs.getString(i)))
                        println()
                    }
                    rs.close()
                }
            }
            taula.close()
        }
        println()
        println("Introdueix un número per veure el contingut de la taula (0 per acabar): ")
        opcio = Integer.parseInt(ent.readLine())
    }
    ll.close()
    con.close()
}