最近打算在应用程序中做数据库元信息读取与相关管理工作,必定会有很需要攻克的技术难关,所以在此写下此文以便日后查阅.
要使用JDBC来获取数据库元信息,则其中有一个对象是必须要了解的,那就是DatabaseMetaData这个对象JDBC规范对数据库元信息的抽取的接口对象,究竟如果开始元信息的读取与管理工作,现在我也不是十分的清楚,便是其中有几个方面我是比较关注的那就是:关于表,表中的列,因为在业务系统这些信息是非常重要的,那么就先从别人的一篇关于获取表的文章开始元信息的历程吧.
实现原理:主要是利用DatabaseMetaData.getTables(...)这个方法实现的,但是每一种数据库还存在一些差异,具体见下面详解。一起jquery,17jquery
一、getTables(...)方法说明
ResultSet DatabaseMetaData.getTables(String catalog,
String schemaPattern,
String tableNamePattern,
String types[]) throws SQLException;
- catalog - 数据库目录名称,可设为null,(具体JDBC驱动的实现不一样在MySQL中指数据库名)。
- schemaPattern - 方案名称的样式,可设为null,( 具体JDBC驱动的实现不一样, 在Oracle中指用户名)。
- tableNamePattern - 表名称的样式,可以包含匹配符比如:"TEST%"
- types - 要包括的表类型组成的列表,可设为null,表示所有的。types的常量值为:"TABLE","VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL TEMPORARY", "ALIAS", "SYNONYM"
各种数据库系统对Catalog和Schema的支持和实现方式是不一样的,针对具体问题需要参考具体的产品说明书,比较简单而常用的实现方式是使用数据库名作为Catalog名,使用用户名作为Schema名,具体可参见下表:
常用数据库Catalog和Schema对照表
供应商 | Catalog支持 | Schema支持 |
Oracle | 不支持 | Oracle User ID |
MySQL | 不支持 | 数据库名 |
MS SQL Server 内容 | 数据库名 | 对象属主名,2005版开始有变 |
DB2 | 指定数据库对象时,Catalog部分省略 | Catalog属主名 |
Sybase 一起 | 数据库名 | 数据库属主名 |
Informix | 不支持 | 不需要 |
PointBase | 不支持 | 数据库名 |
我自己对数据库实际厂商对catalog支持的测试结果如下:
catalog这个单词的中文意思为"目录",具体JDBC规范中,不同的数据库对它的解释是不<br>
* 一样的具体情况是:oracle与hsql中没有任何意义,总是返回null值;而对于myslq与<br>
* sqlserver数据这个属性被解释为数据库名称,或称为数据库实例名称就是在JDBC连接<br>
* 中的URL最后的那个部分,三个典型数据连接情况可以是下面的某种样式:<br>
* jdbc:oracle:thin:@127.0.0.1:1521:ORCL<br>
* jdbc:mysql://127.0.0.1:3306/test<br>
* jdbc:jtds:sqlserver://127.0.0.1:1433/pubs<br>
* 那么在mysql中catalog被解释成test,而在sqlserver中catalog被解释成pubs,<br>
* 而在oracle中catalog并不解释成ORCL.这可能与数据本身的实现机制有关系,至于<br>
* oracle为什么要将catalog解释为null值我并不十分的清楚,我推测oracle数据库<br>
* 在结构似乎比其它数据多一个层次,其它厂商所谓的多个数据库实例有点类似于oracle<br>
* 数据的表空间的概念,oracle自己的实例似乎比这个还要高一个层次.<br>
* 究竟是什么意思就不去管它了,只要知道在oracle中的这个catalog是没有意义的
内容来自17jquery
二、常用数据库举例
1. MySQL示例
url = jdbc:mysql://localhost:3306/michaeldemo
user = "root";
getTables("michaeldemo", null, tableName,new String[] { "TABLE" });
看到这有人会问,你上面的对照表中不是说过MySQL不支持Catalog,而是支持Schema,这里怎么又设置第一个参数呢?不是互相矛盾么?的确是有这个疑问,不过当你看过MySQL的JDBC驱动源码后你就会明白其中原因了,我摘录一部分实现代码具体如下:
一起jquery,17jquery
String sql = "SELECT TABLE_SCHEMA AS TABLE_CAT, "
+ "NULL AS TABLE_SCHEM, TABLE_NAME, "
+ "CASE WHEN TABLE_TYPE='BASE TABLE' THEN 'TABLE' WHEN TABLE_TYPE='TEMPORARY' THEN 'LOCAL_TEMPORARY' ELSE TABLE_TYPE END AS TABLE_TYPE, "
+ "TABLE_COMMENT AS REMARKS "
+ "FROM INFORMATION_SCHEMA.TABLES WHERE "
+ "TABLE_SCHEMA LIKE ? AND TABLE_NAME LIKE ? AND TABLE_TYPE IN (?,?,?) "
+ "ORDER BY TABLE_TYPE, TABLE_SCHEMA, TABLE_NAME"; 内容来自17jquery
可知参数catalog在MySQL中实际是当做Schema来用的,所以这就解释了为什么mysql中设置的却是参数catalog的值。
2. Oracle示例
url = jdbc:oracle:thin:@localhost:1521:ORA11g
user = "demo";
getTables(null, "DEMO", tableName,new String[] { "TABLE" });
一起jquery,17jquery
二、测试代码
JdbcCheckTableExitDemo.java
package michael.jdbc;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @blog http://sjsky.iteye.com
* @author Michael
*/
public class JdbcCheckTableExitDemo {
private static String url = "jdbc:mysql://localhost:3306/michaeldemo";
private static String user = "root";
private static String password = "";
private static String driver = "com.mysql.jdbc.Driver";
// private static String url = "jdbc:oracle:thin:@localhost:1521:ORA11g";
// private static String user = "demo";
// private static String password = "111111";
// private static String driver = "oracle.jdbc.driver.OracleDriver";
/**
* @param args
*/
public static void main(String[] args) {
Connection conn = null;
String tableName = "TB_MYTEST";
try {
Class.forName(driver);
conn = DriverManager.getConnection(url, user, password);
conn.setAutoCommit(false);
DatabaseMetaData meta = conn.getMetaData();
// 第一个参数catalog在MySQL中对应数据库名:michaeldemo
ResultSet rsTables = meta.getTables("michaeldemo", null, tableName,
new String[] { "TABLE" });
// 第二个参数schemaPattern在ORACLE中对应用户名:demo
// ResultSet rsTables = meta.getTables(null, "DEMO", tableName,
// new String[] { "TABLE" });
System.out.println("getTables查询信息如下:");
System.out
.println("TABLE_CAT \t TABLE_SCHEM \t TABLE_NAME \t TABLE_TYPE");
while (rsTables.next()) {
System.out.println(rsTables.getString("TABLE_CAT") + "\t"
+ rsTables.getString("TABLE_SCHEM") + "\t"
+ rsTables.getString("TABLE_NAME") + "\t"
+ rsTables.getString("TABLE_TYPE"));
}
rsTables.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != conn) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Oracle中运行结果:
getTables查询信息如下:
TABLE_CAT TABLE_SCHEM TABLE_NAME TABLE_TYPE
null DEMO TB_MYTEST TABLE
MySQL中运行结果:内容来自17jquery
getTables查询信息如下:
TABLE_CAT TABLE_SCHEM TABLE_NAME TABLE_TYPE
michaeldemo null TB_MYTEST TABLE