借助JDBC元數(shù)據(jù)API,發(fā)現(xiàn)數(shù)據(jù)庫元數(shù)據(jù)
譯文【51CTO.com快譯】元數(shù)據(jù)基本上是指這類數(shù)據(jù),提供關(guān)于其他一些數(shù)據(jù)的結(jié)構(gòu)化描述。從程序員的角度來看,數(shù)據(jù)庫元數(shù)據(jù)是指關(guān)于數(shù)據(jù)庫數(shù)據(jù)的數(shù)據(jù),或者更準(zhǔn)確地說,是關(guān)于表、視圖、列類型、列名稱、結(jié)果集、存儲過程和數(shù)據(jù)庫的信息。Java的JDBC元數(shù)據(jù)API提供了通過Java代碼檢索該信息的手段。Java元數(shù)據(jù)信息尤其有助于編寫可以適應(yīng)幾個數(shù)據(jù)庫系統(tǒng)或適應(yīng)任何數(shù)據(jù)庫內(nèi)容的代碼。這意味著,創(chuàng)建一類泛型接口,使用高級數(shù)據(jù)庫功能,在運行時發(fā)現(xiàn)數(shù)據(jù)庫元數(shù)據(jù)。本文試圖探究JDBC元數(shù)據(jù)API的一些關(guān)鍵特性,以便有助于發(fā)現(xiàn)數(shù)據(jù)庫元數(shù)據(jù)。
元數(shù)據(jù)的使用
JDBC元數(shù)據(jù)API可用于檢索關(guān)于數(shù)據(jù)庫的下列信息:
- 數(shù)據(jù)庫用戶、表、視圖和存儲過程
- 數(shù)據(jù)庫模式和目錄信息
- 表、視圖和列權(quán)限
- 關(guān)于表的主密鑰或外來密鑰的信息
JDBC概況
JDBC為客戶機應(yīng)用程序提供了必要的API,以便借助元數(shù)據(jù)類,發(fā)現(xiàn)關(guān)于數(shù)據(jù)庫和任何特定結(jié)果集(ResultSet)的信息。
圖1:JDBC概況
API涉及為客戶機提供元數(shù)據(jù)信息服務(wù)的幾個接口??蛻魴C通過JDBC驅(qū)動程序管理器(JDBC Driver Manager),檢索該信息。驅(qū)動程序管理器充當(dāng)實際數(shù)據(jù)庫和API之間的接口。針對特定廠商的數(shù)據(jù)庫提供了自己的Java驅(qū)動程序(類型4驅(qū)動程序)。比如說,MySQL提供了Connector/J;甲骨文或PostgreSQL等其他數(shù)據(jù)庫有各自的JDBC驅(qū)動程序。在數(shù)據(jù)庫廠商不提供任何驅(qū)動程序(類型4)的情況下,Java IDBC/ODBC Bridge可充當(dāng)?shù)讓覱DBC驅(qū)動程序和驅(qū)動程序管理器之間的中介。不管在什么情況下,檢索數(shù)據(jù)庫元數(shù)據(jù)信息的方法都是一樣的。
JDBC元數(shù)據(jù)API
JDBC API提供了檢索元數(shù)據(jù)信息的兩個關(guān)鍵接口:DatabaseMetaData和ResultSetMetaData。這兩個接口是java.sql程序包的一部分。DatabaseMetaData主要用于檢索關(guān)于數(shù)據(jù)庫的信息,比如其功能和結(jié)構(gòu)。另一方面,ResultSetMetaData用于獲得關(guān)于SQL查詢的信息,比如關(guān)于其大小和列類型的信息。所以,JDBC元數(shù)據(jù)API的關(guān)鍵要素如下:
DatabaseMetaData
該接口通常由數(shù)據(jù)庫廠商來實施,與原生JDBC驅(qū)動程序一道提供。原生JDBC驅(qū)動程序建立在數(shù)據(jù)庫上面。通過實施該接口,數(shù)據(jù)庫廠商提供了關(guān)于整個數(shù)據(jù)庫的綜合信息,比如表名稱、索引、產(chǎn)品名稱和版本等信息。該接口中聲明了許多方法,以便檢索與數(shù)據(jù)庫有關(guān)的各種元數(shù)據(jù)信息。
簡短例子
- 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
該接口提供了關(guān)于ResultSet對象結(jié)構(gòu)的元數(shù)據(jù)信息,比如搞清楚列數(shù)量、名稱、類型和長度、表名稱、列是可讀/可寫還是可搜索等。
簡短例子
- 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對象用來檢索關(guān)于PreparedStatement對象中參數(shù)標(biāo)記的信息。元數(shù)據(jù)信息是指所用參數(shù)的類型和屬性,比如獲得完全合格的Java類名稱、參數(shù)數(shù)量、類型、列大小確定的指定精度等。
簡短例子
- 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接口的子實現(xiàn)。這類對象提供了RowSet對象中列的信息。RowSet接口為JavaBeans組件模型提供了支持JDBC API的功能。因而,它有屬性,可支持JavaBeans事件通知方法。RowSetMetadata提供了關(guān)于RowSet對象中列的信息,可以用來查明行集中所含列的數(shù)量,或每一列所含數(shù)據(jù)的類型。了解RowSet對象的工作機制至關(guān)重要,以便完全了解RowSetMetaData的使用。描述rowset機制不在本文探討范圍之內(nèi);不過,讀者可能會喜歡這篇文章《使用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) {
- }
- }
- }
- }
結(jié)束語
以這些例子作為一個出發(fā)點,以此試用JDC元數(shù)據(jù)API。JDBC元數(shù)據(jù)API是創(chuàng)建大多數(shù)商業(yè)數(shù)據(jù)庫應(yīng)用程序所必不可少的。它們尤其適用于創(chuàng)建定制的數(shù)據(jù)庫解決方案,比如生成基于GUI的數(shù)據(jù)瀏覽器應(yīng)用程序。比如說,你可以根據(jù)從數(shù)據(jù)庫檢索的元數(shù)據(jù)信息,動態(tài)創(chuàng)建一個基于GUI的表結(jié)構(gòu)。想了解關(guān)于API及其功能的更多信息,請參閱Java API說明文檔。
原文標(biāo)題:Discovering Database Metadata with the JDBC Metadata API
原文作者:Manoj Debnath
【51CTO譯稿,合作站點轉(zhuǎn)載請注明原文譯者和出處為51CTO.com】