W3docs

Java JDBC Metadata

Inspect databases and result sets at runtime in Java with DatabaseMetaData and ResultSetMetaData.

Java JDBC Metadata

Metadata is data about the data — the shape of a result set and the capabilities of the database, rather than the rows themselves. JDBC exposes two metadata interfaces, and they answer different questions. They power generic tools: row printers, schema browsers, ORMs, and migration scripts that must work without hard-coded knowledge of the tables.

ResultSetMetaData — describing a query's columns

Call rs.getMetaData() to learn what columns a query returned: how many, their names, and their SQL types. This is how a generic grid renders any query:

ResultSetMetaData md = rs.getMetaData();
int n = md.getColumnCount();
for (int i = 1; i <= n; i++) {   // 1-based, of course
  System.out.println(md.getColumnLabel(i)
      + " : " + md.getColumnTypeName(i)
      + " (java.sql.Types " + md.getColumnType(i) + ")");
}

Key methods: getColumnCount(), getColumnLabel(i) (the display name, honoring AS aliases), getColumnType(i) (the java.sql.Types int code), getColumnTypeName(i) (the vendor's name), and isNullable(i).

DatabaseMetaData — describing the database

Call conn.getMetaData() for facts about the database and driver themselves: product name and version, supported features, and the catalog of tables, columns, keys, and indexes.

DatabaseMetaData dbmd = conn.getMetaData();
System.out.println(dbmd.getDatabaseProductName() + " " + dbmd.getDatabaseProductVersion());
System.out.println("supports transactions: " + dbmd.supportsTransactions());

// the schema catalog comes back as ResultSets you read normally
try (ResultSet tables = dbmd.getTables(null, null, "%", new String[]{"TABLE"})) {
  while (tables.next()) System.out.println(tables.getString("TABLE_NAME"));
}

Notice that getTables, getColumns, and friends return ResultSets — the catalog is queried with the same cursor API as any other data.

Mapping type codes to names

getColumnType(i) gives an int — one of the java.sql.Types constants. Turning that code into something human-readable (or deciding which getXxx to call) means mapping the code back to its name, which a generic reader builds once and reuses.

A worked example: a type-code dictionary and a column report

This program builds the int→name dictionary for every java.sql.Types constant, then uses it to describe a hypothetical three-column result the way ResultSetMetaData would — and lists the kinds of questions DatabaseMetaData answers — without a live database.

java— editable, runs on the server

What to take from the run:

  • There are 39 standard java.sql.Types codes, and the program builds the whole code→name map by reflecting over the Types class. A real generic reader builds this dictionary once and reuses it for every result set.
  • ResultSetMetaData.getColumnType(i) returns one of these int codes; the dictionary turns code 4 into INTEGER, 12 into VARCHAR, 93 into TIMESTAMP. That lookup is exactly what lets a tool render any query without knowing its columns in advance.
  • The per-column report — name plus type — is what getColumnLabel/getColumnType give you for a real query. It is the foundation of grid viewers, CSV exporters, and ORMs that map columns to fields.
  • DatabaseMetaData answers a different class of question: not "what did this query return" but "what can this database do" — its product name, driver version, feature support, and table catalog.
  • Crucially, the catalog methods (getTables, getColumns) hand back ResultSets, so you read database structure with the very same cursor loop you use for data. Metadata is not a special API — it is data about data, delivered the same way.

Practice

Practice

You are writing a generic tool that must print the column names and types of any SQL query it is given, with no prior knowledge of the schema. Which interface gives you that information?