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.
What to take from the run:
- There are 39 standard
java.sql.Typescodes, and the program builds the whole code→name map by reflecting over theTypesclass. A real generic reader builds this dictionary once and reuses it for every result set. ResultSetMetaData.getColumnType(i)returns one of theseintcodes; the dictionary turns code4intoINTEGER,12intoVARCHAR,93intoTIMESTAMP. 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/getColumnTypegive you for a real query. It is the foundation of grid viewers, CSV exporters, and ORMs that map columns to fields. DatabaseMetaDataanswers 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 backResultSets, 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
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?