1.介绍
JDBC提供了一个 Java API 来读取存储在数据库表中的实际数据。除此之外,还可以使用相同的 API 读取有关数据库的元数据。元数据是指有关数据的数据,例如表名、列名和列类型。
本文介绍
如何使用DatabaseMetaData接口提取不同类型的元数据。
2. DatabaseMetaData的接口
DatabaseMetaData是一个接口,提供了多种方法来获取有关数据库的综合信息。**此信息对于创建允许用户探索不同数据库结构的数据库工具很有用。**当想检查底层数据库是否支持某些功能时,它也很有帮助。
需要一个DatabaseMetaData*实例 来获取此信息。看看如何从Connection对象中获取它:
DatabaseMetaData databaseMetaData = connection.getMetaData();
这里,连接是JdbcConnection 的一个实例。因此,getMetaData()方法返回一个JdbcDatabaseMetaData对象,该对象实现了DatabaseMetaData接口。
3.表元数据
通过DatabaseMetaData对象的getTables()方法,可以获取用户定义的表、系统表、视图名称;还有表的注释。
以下示例演示如何提取所有现有用户定义表的名称:
/**
* 获取数据库表和表注释
* TABLE_CAT String => 表目录(可能为空)
* TABLE_SCHEM 字符串 => 表模式(可能为空)
* TABLE_NAME 字符串 => 表名
* TABLE_TYPE 字符串 => 表类型。 典型的类型有“TABLE”、“VIEW”、“SYSTEM TABLE”、“GLOBAL TEMPORARY”、“LOCAL TEMPORARY”、“ALIAS”、“SYNONYM”。
* REMARKS String => 表上的解释性注释
* TYPE_CAT String => 类型目录(可能为空)
* TYPE_SCHEM String => 类型架构(可能为空)
* TYPE_NAME String => 类型名称(可能为空)
* SELF_REFERENCING_COL_NAME String => 类型表的指定“标识符”列的名称(可能为空)
* REF_GENERATION String => 指定如何创建 SELF_REFERENCING_COL_NAME 中的值。 值为“SYSTEM”、“USER”、“DERIVED”。 (可能为空)
* 最后一个参数 "TABLE", "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
* @throws SQLException SQLException
*/
@Test
public void testTableMeta() throws SQLException {
DatabaseMetaData databaseMetaData = connection.getMetaData();
HashMap<String, String> map = Maps.newHashMap();
//catalog mysql只数据那个数据 不指定就是全部 当前连接下全部数据库
//tableNamePattern (只支持模糊查询和精确查询)查询 oa_sync_% 开头的表名
ResultSet resultSet = databaseMetaData.getTables("test", null, "oa_sync%", new String[]{
"TABLE"});
while (resultSet.next()) {
String tableName = resultSet.getString("TABLE_NAME");
String tableSchem = resultSet.getString("TABLE_SCHEM");
String tableCat = resultSet.getString("TABLE_CAT");
String remarks = resultSet.getString("REMARKS");
map.put(tableName, remarks);
System.out.println(tableCat + ":" + tableSchem);
}
System.out.println(map);
}
前两个参数是catalog和schema。第三个参数采用表名模式。例如,支持模糊比配“CUST%”,这将包括名称以“CUST”开头的所有表。最后一个参数采用包含表类型的字符串数组。将*TABLE*用于用户定义的表。
参数:catalog:目录名称,一般都为空.
参数:schema:数据库名,对于oracle来说就用户名
参数:tablename:表名称
参数:type :表的类型(TABLE | VIEW)
下面示列演示,要查找系统定义的表,将表类型替换为“SYSTEM TABLE”:
ResultSet resultSet = databaseMetaData.getTables(null, null, null, new String[]{
"SYSTEM TABLE"});
while(resultSet.next()) {
String systemTableName = resultSet.getString("TABLE_NAME");
}
最后,要找出所有现有的视图们只需将类型更改为VIEW。
4. 列元数据
可以使用相同的DatabaseMetaData对象获取特定表的列
/**
* 查询字段信息
*
* @throws SQLException SQLException
*/
@Test
public void testTableCol() throws SQLException {
DatabaseMetaData databaseMetaData = connection.getMetaData();
//具体能返回哪些字段 可查询注释
//返回test数据库下所有的列表
ResultSet columns = databaseMetaData.getColumns("test", null, null, null);
while (columns.next()) {
String tableName = columns.getString("TABLE_NAME");
String columnName = columns.getString("COLUMN_NAME");
String columnSize = columns.getString("COLUMN_SIZE");
String datatype = columns.getString("DATA_TYPE");
String isNullable = columns.getString("IS_NULLABLE");
String isAutoIncrement = columns.getString("IS_AUTOINCREMENT");
System.out.println("tableName:" + tableName + ";columnName:" + columnName + ";columnSize:" + columnSize + ";datatype:" + datatype + ";isNullable:" + isNullable + ";isAutoIncrement:" + isAutoIncrement);
}
}
getColumns()调用返回一个ResultSet ,可以迭代它以找到每列的描述。每个描述都包含许多有用的列,例如COLUMN_NAME*、*COLUMN_SIZE和DATA_TYPE,具体包含哪些可查看接口上注释。
除了常规列,还可以找出特定表的主键列:
/**
* 获取表主键信息
*
* @throws SQLException SQLException
*/
@Test
public void testPrimaryKey() throws SQLException {
DatabaseMetaData databaseMetaData = connection.getMetaData();
//必须指定表名
ResultSet foreignKeys = databaseMetaData.getPrimaryKeys(null, null, "oa_sync_dept");
while (foreignKeys.next()) {
String tableName = foreignKeys.getString("TABLE_NAME");
String columnName = foreignKeys.getString("COLUMN_NAME");
//key所在的序列
String keySeq = foreignKeys.getString("KEY_SEQ");
String pkName = foreignKeys.getString("PK_NAME");
System.out.println("tableName:" + tableName + ";columnName:" + columnName + ";keySeq:" + keySeq + ";pkName:" + pkName);
}
}
5. 用户名和架构元数据
可以获取获取连接时用户名
String userName = databaseMetaData.getUserName();
可以使用getSchemas()方法来检索数据库中可用模式的名称:
ResultSet schemas = databaseMetaData.getSchemas();
while (schemas.next()){
String table_schem = schemas.getString("TABLE_SCHEM");
String table_catalog = schemas.getString("TABLE_CATALOG");
}
6. 数据库级元数据
使用相同的DatabaseMetaData 对象获取数据库级别的信息。
以下示例是获取数据库产品的名称和版本、JDBC 驱动程序的名称、JDBC 驱动程序的版本号等。
@Test
public void testDbMetaInfo() throws SQLException{
DatabaseMetaData databaseMetaData = connection.getMetaData();
//数据库产品名称
String productName = databaseMetaData.getDatabaseProductName();
//数据库版本
String productVersion = databaseMetaData.getDatabaseProductVersion();
//驱动名
String driverName = databaseMetaData.getDriverName();
//驱动版本
String driverVersion = databaseMetaData.getDriverVersion();
System.out.println("productName:"+productName+";productVersion:"+productVersion+";driverName:"+driverName+";driverVersion:"+driverVersion);
了解此信息有时很有用,尤其是当应用程序针对多个数据库产品和版本运行时。例如,某个版本或产品可能缺少特定功能或包含应用程序需要实施某种解决方法的错误。
7. 数据库支持的功能元数据
不同的数据库支持不同的功能
如何知道使用的数据库是否支持某个功能,以下代码进行功能演示
@Test
public void testDbSupport() throws SQLException {
DatabaseMetaData databaseMetaData = connection.getMetaData();
//是否支持外连接
boolean supportsFullOuterJoins = databaseMetaData.supportsFullOuterJoins();
//是否支持存储过程
boolean supportsStoredProcedures = databaseMetaData.supportsStoredProcedures();
//是否支持事务
boolean supportsTransactions = databaseMetaData.supportsTransactions();
//是否支持批量更新
boolean supportsBatchUpdates = databaseMetaData.supportsBatchUpdates();
System.out.println("supportsFullOuterJoins:"+supportsFullOuterJoins+";supportsStoredProcedures:"
+supportsStoredProcedures+";supportsTransactions:"+supportsTransactions+";supportsBatchUpdates:"+supportsBatchUpdates);
}