[ Team LiB ] Previous Section Next Section

18.2 Using Database Metadata

Sometimes, in addition to querying and updating the data in a database, you also want to retrieve information about the database itself and its contents. This information is called metadata. The DatabaseMetaData interface allows you to retrieve this kind of information. You can obtain an object that implements this interface by calling the getMetaData( ) method of the Connection object, as shown in Example 18-2.

After GetDBInfo opens a database Connection and obtains a DatabaseMetaData object, it displays some general information about the database server and JDBC driver. Then, if the user just specified a database name on the command line, the program lists all the tables in that database. If the user specified a database name and a table name, however, the program lists the name and data type of each column in that table.

An interesting feature of this GetDBInfo program is how it obtains the parameters needed to connect to the database. The example operates on the premise that at any given site, it is typically used to connect to the same database server, using the same database driver, and may also be used with the same database username and password. So, instead of requiring the user to type all this cumbersome information on the command line each time the program is run, the program reads default values from a file named DB.props that is stored in the same directory as the GetDBInfo.class file. In order to run Example 18-2, you have to create an appropriate DB.props file for your system. On my system, this file contains:

# The name of the JDBC driver class
# The URL that specifies the database server.
# It should not include the name of the database to connect to
# The database account name
# The password for the specified account, if any.
# Uncomment the line below if you need to specify a password

Lines that begin with # are comments, obviously. The name=value format is the standard file format for the java.util.Properties object that is used to read the contents of this file.

After the program reads the default values from the DB.props file, it parses its command-line arguments, which can override the driver, server, user, and password properties specified in the file. The name of the database to connect to must be specified on the command line; the database name is simply appended to the server URL. The name of a table in the database can optionally be specified on the command line. For example, you might run the program as follows:

% java je3.sql.GetDBInfo api class
DBMS: MySQL 4.0.14-standard
JDBC Driver: MySQL-AB JDBC Driver 3.0.8-stable ($Date: 2004/01/29 23:10:56 $)
Database: jdbc:mysql:///apidb
User: david@localhost
Columns of class:
        id : int
        packageId : int
        name : varchar
Example 18-2. GetDBInfo.java
package je3.sql;
import java.sql.*;
import java.util.Properties;

 * This class uses the DatabaseMetaData class to obtain information about
 * the database, the JDBC driver, and the tables in the database, or about
 * the columns of a named table.
public class GetDBInfo {
    public static void main(String[  ] args) {
        Connection c = null;  // The JDBC connection to the database server
        try {
            // Look for the properties file DB.props in the same directory as
            // this program.  It will contain default values for the various
            // parameters needed to connect to a database
            Properties p = new Properties( );
            try { p.load(GetDBInfo.class.getResourceAsStream("DB.props")); }
            catch (Exception e) {  }
            // Get default values from the properties file
            String driver = p.getProperty("driver");     // Driver class name
            String server = p.getProperty("server", ""); // JDBC URL for server
            String user = p.getProperty("user", "");     // db user name
            String password = p.getProperty("password", ""); // db password
            // These variables don't have defaults
            String database = null; // The db name (appended to server URL)
            String table = null;    // The optional name of a table in the db
            // Parse the command-line args to override the default values above
            for(int i = 0; i < args.length; i++) {
                if (args[i].equals("-d")) driver = args[++i];     //-d <driver>
                else if (args[i].equals("-s")) server = args[++i];//-s <server>
                else if (args[i].equals("-u")) user = args[++i];  //-u <user>
                else if (args[i].equals("-p")) password = args[++i]; 
                else if (database == null) database = args[i];    // <dbname>
                else if (table == null) table = args[i];          // <table>
                else throw new IllegalArgumentException("Unknown argument: "

            // Make sure that at least a server or a database were specified. 
            // If not, we have no idea what to connect to, and cannot continue.
            if ((server.length( ) == 0) && (database.length( ) == 0))
                throw new IllegalArgumentException("No database specified.");

            // Load the db driver, if any was specified.
            if (driver != null) Class.forName(driver);
            // Now attempt to open a connection to the specified database on
            // the specified server, using the specified name and password
            c = DriverManager.getConnection(server+database, user, password);

            // Get the DatabaseMetaData object for the connection.  This is the
            // object that will return us all the data we're interested in here
            DatabaseMetaData md = c.getMetaData( );

            // Display information about the server, the driver, etc.
            System.out.println("DBMS: " + md.getDatabaseProductName( ) + 
                               " " + md.getDatabaseProductVersion( ));
            System.out.println("JDBC Driver: " + md.getDriverName( ) + 
                               " " + md.getDriverVersion( ));
            System.out.println("Database: " + md.getURL( ));
            System.out.println("User: " + md.getUserName( ));

            // Now, if the user did not specify a table, then display a list of
            // all tables defined in the named database.  Note that tables are
            // returned in a ResultSet, just like query results are.
            if (table == null) {
                ResultSet r = md.getTables("", "", "%", null);
                while(r.next( )) System.out.println("\t" + r.getString(3));

            // Otherwise, list all columns of the specified table.
            // Again, information about the columns is returned in a ResultSet
            else {
                System.out.println("Columns of " + table + ": ");
                ResultSet r = md.getColumns("", "", table, "%");
                while(r.next( )) 
                    System.out.println("\t" + r.getString(4) + " : " +
        // Print an error message if anything goes wrong.
        catch (Exception e) {
            if (e instanceof SQLException)
                System.err.println(((SQLException)e).getSQLState( ));
            System.err.println("Usage: java GetDBInfo [-d <driver>] " +
                               "[-s <dbserver>]\n" +
                               "\t[-u <username>] [-p <password>] <dbname>");
        // Always remember to close the Connection object when we're done!
        finally { 
            try { c.close( ); } catch (Exception e) {  }
    [ Team LiB ] Previous Section Next Section