【51CTO.com快译】元数据基本上是指这类数据,提供关于其他一些数据的结构化描述。从程序员的角度来看,数据库元数据是指关于数据库数据的数据,或者更准确地说,是关于表、视图、列类型、列名称、结果集、存储过程和数据库的信息。Java的JDBC元数据API提供了通过Java代码检索该信息的手段。Java元数据信息尤其有助于编写可以适应几个数据库系统或适应任何数据库内容的代码。这意味着,创建一类泛型接口,使用高级数据库功能,在运行时发现数据库元数据。本文试图探究JDBC元数据API的一些关键特性,以便有助于发现数据库元数据。
元数据的使用
JDBC元数据API可用于检索关于数据库的下列信息:
- 数据库用户、表、视图和存储过程
- 数据库模式和目录信息
- 表、视图和列权限
- 关于表的主密钥或外来密钥的信息
JDBC概况
JDBC为客户机应用程序提供了必要的API,以便借助元数据类,发现关于数据库和任何特定结果集(ResultSet)的信息。
图1:JDBC概况
API涉及为客户机提供元数据信息服务的几个接口。客户机通过JDBC驱动程序管理器(JDBC Driver Manager),检索该信息。驱动程序管理器充当实际数据库和API之间的接口。针对特定厂商的数据库提供了自己的Java驱动程序(类型4驱动程序)。比如说,MySQL提供了Connector/J;甲骨文或PostgreSQL等其他数据库有各自的JDBC驱动程序。在数据库厂商不提供任何驱动程序(类型4)的情况下,Java IDBC/ODBC Bridge可充当底层ODBC驱动程序和驱动程序管理器之间的中介。不管在什么情况下,检索数据库元数据信息的方法都是一样的。
JDBC元数据API
JDBC API提供了检索元数据信息的两个关键接口:DatabaseMetaData和ResultSetMetaData。这两个接口是java.sql程序包的一部分。DatabaseMetaData主要用于检索关于数据库的信息,比如其功能和结构。另一方面,ResultSetMetaData用于获得关于SQL查询的信息,比如关于其大小和列类型的信息。所以,JDBC元数据API的关键要素如下:
DatabaseMetaData
该接口通常由数据库厂商来实施,与原生JDBC驱动程序一道提供。原生JDBC驱动程序建立在数据库上面。通过实施该接口,数据库厂商提供了关于整个数据库的综合信息,比如表名称、索引、产品名称和版本等信息。该接口中声明了许多方法,以便检索与数据库有关的各种元数据信息。
简短例子
- package org.mano.example;
- import java.sql.Connection;
- import java.sql.DatabaseMetaData;
- import java.sql.DriverManager;
- import java.sql.SQLException;
- public class DatabaseMetaDataDemo {
- private static final String URL =
- "jdbc:mysql://localhost:3306/addressbook?
- zeroDateTimeBehavior=convertToNull";
- private static final String USERNAME = "testuser";
- private static final String PASSWORD = "secret";
- public static void main(String[] args) {
- Connection conn = null;
- DatabaseMetaData dbmd = null;
- try {
- conn = DriverManager.getConnection(URL, USERNAME,
- PASSWORD);
- dbmd = conn.getMetaData();
- if (dbmd != null) {
- System.out.println("Database Version: " +
- dbmd.getDatabaseProductVersion());
- System.out.println("Driver Name: " +
- dbmd.getDriverName());
- System.out.println("Driver Version: " +
- dbmd.getDriverVersion());
- System.out.println("URL: " +
- dbmd.getURL());
- System.out.println("User Name: " +
- dbmd.getUserName());
- System.out.println(
- (dbmd.supportsANSI92FullSQL() ?
- "ANSI92FullSQL supported." :
- "ANSI92FullSQL not supported."));
- System.out.println(
- (dbmd.supportsTransactions() ?
- "Transaction supported." :
- "Transaction not supported."));
- } else {
- System.out.println("Metadata not supported");
- }
- } catch (SQLException ex1) {
- System.err.println(ex1);
- } finally {
- try {
- conn.close();
- } catch (SQLException ex2) {
- }
- }
- }
- }
ResultSetMetaData
该接口提供了关于ResultSet对象结构的元数据信息,比如搞清楚列数量、名称、类型和长度、表名称、列是可读/可写还是可搜索等。
简短例子
- package org.mano.example;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.ResultSet;
- import java.sql.ResultSetMetaData;
- import java.sql.SQLException;
- import java.sql.Statement;
- public class ResultSetMetaDataDemo {
- private static final String URL =
- "jdbc:mysql://localhost:3306/addressbook?
- zeroDateTimeBehavior=convertToNull";
- private static final String USERNAME = "testuser";
- private static final String PASSWORD = "secret";
- private static final String SQL =
- "SELECT * FROM Addresses";
- public static void main(String[] args) {
- Connection conn = null;
- Statement stmt = null;
- ResultSet rs = null;
- ResultSetMetaData rsmd = null;
- try {
- conn = DriverManager.getConnection(URL,
- USERNAME, PASSWORD);
- stmt = conn.createStatement();
- rs = stmt.executeQuery(SQL);
- rsrsmd = rs.getMetaData();
- if (rsmd != null) {
- int cols = rsmd.getColumnCount();
- System.out.println("Number of Columns: " + cols);
- System.out.println("Table Name: " +
- rsmd.getTableName(1));
- System.out.println("Catalog Name: " +
- rsmd.getCatalogName(1));
- System.out.println
- ("------------------------------------------");
- for (int i = 1; i <= cols; i++) {
- System.out.println("Class Name: " +
- rsmd.getColumnClassName(i));
- System.out.println("Column Name: " +
- rsmd.getColumnName(i));
- System.out.println("Column Type Name: " +
- rsmd.getColumnTypeName(i));
- System.out.println
- ("--------------------------------------");
- }
- } else {
- System.out.println("ResultSetMetadata not supported");
- }
- } catch (SQLException ex1) {
- System.err.println(ex1);
- } finally {
- try {
- stmt.close();
- rs.close();
- conn.close();
- } catch (SQLException ex2) {
- }
- }
- }
- }
ParameterMetaData
ParameterMetadata对象用来检索关于PreparedStatement对象中参数标记的信息。元数据信息是指所用参数的类型和属性,比如获得完全合格的Java类名称、参数数量、类型、列大小确定的指定精度等。
简短例子
- package org.mano.example;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.ParameterMetaData;
- import java.sql.PreparedStatement;
- import java.sql.SQLException;
- public class ParameterMetaDataDemo {
- private static final String URL = "jdbc:mysql://localhost:3306/
- addressbook?zeroDateTimeBehavior=convertToNull";
- private static final String USERNAME = "testuser";
- private tatic final String PASSWORD = "secret";
- private static final String SQL = "SELECT id, firstName, lastName
- FROM Addresses WHERE id=? AND firstName LIKE ?";
- public static void main(String[] args) {
- Connection conn = null;
- PreparedStatement pstmt = null;
- ParameterMetaData pmd = null;
- try {
- conn = DriverManager.getConnection(URL,
- USERNAME, PASSWORD);
- pstmt = conn.prepareStatement(SQL);
- pmd = pstmt.getParameterMetaData();
- if (pmd != null) {
- System.out.println("Parameter Count: " +
- pmd.getParameterCount());
- } else {
- System.out.println("ParameterMetadata not
- supported by the database");
- }
- catch (SQLException ex1) {
- System.err.println(ex1);
- } finally {
- try {
- pstmt.close();
- conn.close();
- } catch (SQLException ex2) {
- }
- }
- }
- }
RowSetMetaData接口是javax.sql程序包的一部分,也是ResultSetMetaData接口的子实现。这类对象提供了RowSet对象中列的信息。RowSet接口为JavaBeans组件模型提供了支持JDBC API的功能。因而,它有属性,可支持JavaBeans事件通知方法。RowSetMetadata提供了关于RowSet对象中列的信息,可以用来查明行集中所含列的数量,或每一列所含数据的类型。了解RowSet对象的工作机制至关重要,以便完全了解RowSetMetaData的使用。描述rowset机制不在本文探讨范围之内;不过,读者可能会喜欢这篇文章《使用JDBC RowSet API》(http://www.developer.com/java/working-with-the-jdbc-rowset-api.html),大致了解Rowset API。然而,这并不阻止我们大致看一下RowSetMetaData的实际使用。
简短例子
- package org.mano.example;
- import java.sql.SQLException;
- import javax.sql.RowSetMetaData;
- import javax.sql.rowset.WebRowSet;
- import com.sun.rowset.WebRowSetImpl;
- public class RowSetMetaDataDemo {
- private static final String URL = "jdbc:mysql://localhost:3306/
- addressbook?zeroDateTimeBehavior=convertToNull";
- private static final String USERNAME = "testuser";
- private static final String PASSWORD = "secret";
- private static final String SQL = "SELECT * FROM Addresses";
- public static void main(String[] args) {
- WebRowSet rowSet = null;
- RowSetMetaData rsmd = null;
- try {
- Class.forName("com.mysql.jdbc.Driver");
- rowSet = new WebRowSetImpl();
- rowSet.setUrl(URL);
- rowSet.setUsername(USERNAME);
- rowSet.setPassword(PASSWORD);
- rowSet.setCommand(SQL);
- rowSet.execute();
- rsmd = (RowSetMetaData) rowSet.getMetaData();
- if (rsmd != null) {
- int count = rsmd.getColumnCount();
- for (int i = 1; i <= count; i++)
- System.out.println("Column Name: " +
- rsmd.getColumnName(i) +
- " Type: " + rsmd.getColumnTypeName(i));
- } else {
- System.out.println("RowSetMetadata not supported");
- }
- } catch (ClassNotFoundException | SQLException ex1) {
- System.err.println(ex1);
- } finally {
- try {
- rowSet.close();
- } catch (SQLException ex2) {
- }
- }
- }
- }
结束语
以这些例子作为一个出发点,以此试用JDC元数据API。JDBC元数据API是创建大多数商业数据库应用程序所必不可少的。它们尤其适用于创建定制的数据库解决方案,比如生成基于GUI的数据浏览器应用程序。比如说,你可以根据从数据库检索的元数据信息,动态创建一个基于GUI的表结构。想了解关于API及其功能的更多信息,请参阅Java API说明文档。
原文标题:Discovering Database Metadata with the JDBC Metadata API
原文作者:Manoj Debnath
【51CTO译稿,合作站点转载请注明原文译者和出处为51CTO.com】