DatabaseMetaData开发实务(上)

8 篇文章 0 订阅
1.总论

       在企业开发实务中,数据迁移是经常会遇到的事情,此时,需要搞清楚,源数据库与目的数据库之间表以及表内部各列之间的异同。而有些时候,我们拿到的项目文档,未必能准确表述各个表的准确结构,即使应用建模工具反向导出物理结构,但依靠人工比对,也是很困难的一件事情。而此时, 如果能“反编译数据库”,提取表信息以及表内部各列的信息,然后通过程序自动进行比较,并将比较结果以报表的形式输出,那么这个问题就简单很多了。此间“反编译数据库”要解决两个问题,一个是数据库中每个用户表的名称是什么,另外一个就是对于规定的表名称,其内部结构是什么样的,比如有那些列,每列的数据类型,长度等等信息。基于上述事项,编写本文。上篇阐述Table列表的获取,中篇阐述单一表field列表的获取,下篇完成数据库之间的比较并生成比较报告。

2.数据库表结构的获取

       在JDBC技术规范中,提供了Connection,Statement,ResultSet这三个开发过程中经常用到的接口。针对与每个接口,JDBC规范提供了相应的接口描述对象,也就是xxxMetaData系列描述对象。在本文中我们将会用到DatabaseMetaData和ResultSetMetaData,他们分别描述了数据库的相关信息和结果集的相关信息。

3.遍历数据库的表

3.1DatabaseMetaData对象的获取。

当数据库连接对象(Connection)被创建完毕以后,针对该Connection会存在一个数据库的描述对象,其获取方式如下。

//获取数据库连接对象

conn=DBUtils.getConnection();

//获取描述对象

DatabaseMetaData dbmd=conn.getMetaData();

这个对象包含了conn所连接的数据库的详细信息,有了这些信息我们才好施展手脚。

3.2获取表的定义

       DatabaseMetaData提供了如下方法用来获取数据库表的定义

   //检索数据库中表的类型

   ResultSet getTables(
String catalog,

                       String schemaPattern,

                       String tableNamePattern,

                       String[] types

)

                    throws SQLException

3.2.1参数说明:

    对于该方法的四个参数,总是有些让人迷惑,而相关的资料介绍也并不是很详细,分析相关资料以及通过实际的程序测试,大致可以得出如下结论:

catalog – Stirng形式的类别名称,如果为null,则该参数不作为检索条件,如果为空(””)则获取不带类别的表的信息

schemaPattern – String形式的模式名称,如果为null,则该参数不作为检索条件,如果为空(””)则获取不带模式的表的信息

tableNamePattern –表名称,为null将不作为检索条件

types[] – 获取那些类型的表,每种类型以字符串的形式放入该数组中,典型的表类型一般包括"TABLE"、"VIEW"、"SYSTEM TABLE"、"GLOBAL TEMPORARY"、"LOCAL TEMPORARY"、"ALIAS" 和 "SYNONYM"。该参数可以为null,此时不作为检索条件。一般来说我们要获取的就是表和视图的信息,因此字符传数组types的值一般写成{"TABLE","VIEW"}

结合本文要解决的事项,第三个参数,没有实际的意义,填充null,第四个参数,由于程序中只需要分析表和视图,所以值为“new String[]{"TABLE","VIEW"}”。但是对于前两个参数,针对不同的数据库,其参数值大相径庭。

下面以MySQL和Oracle为例来讲解这个两个参数。

3.2.2 catalog和schema

Oracle和MySQL数据的组织结构是完全不同,直观表象上,表和视图的挂接途径不一样,在Oracle中,采取的是分用户管理机制,表和视图挂接在某个用户下,此时用户会成为Oracle的一个”模式(schema)”;而在MySQL中表和视图是直接挂接在数据库下的。这样,在Oralce中获取catalog得到的是null,获取schema得到大写的是用户名称列表。而在MySQL中得到的catalog是数据库名称列表,而schema是null。读者可以通过DatabaseMetaData提供的如下两个方法进行测试,他们返回的都是ResultSet数据类型。

//获取类别定义

rs=dbmd.getCatalogs();

//获取模式定义

rs=dbmd.getSchemas();

基于上述分析:

如果数据库为MySQL:那么第一个参数catalog,可以是数据库的名称,当该项为null时候,为Url串中指定的数据库名称,第二个参数schema,填入null;

如果数据库为Oralce: 那么第一个参数catalog,为null,第二个参数schema,填入大写的用户名称例如”SCOTT”,如果该项目为null,那么查询范围为所有的模式用户。

3.3返回值分析

       方法getTables返回值是一个结果集(ResultSet)类型,对于该结果集中的信息,到JDK1.5预留了20多个项目用来描述表的相关信息,但是,并不是每个数据都会将这20多个项目返回的. 我们能够常用到的有如下的四个项目:

TABLE_SCHEM:对于Oracle而言,是大写的用户名称,对MySQL而言为null 。

TABLE_NAME:表的名称 。

TABLE_CAT=对Oracle而言为null,对MySQL而言是数据库名称 。

TABLE_TYPE=表的类型,依据第四个参数types数组中的某一项,用以表和视图。

   

4.程序代码:

数据库连接类:DBUtils.java

  

  1. package com.qhit.db;  
  2.   
  3. import java.sql.*;  
  4.   
  5. public class DBUtils  
  6. {  
  7.     private static String Driver = "com.mysql.jdbc.Driver";  
  8.     private static String Url = "jdbc:mysql://localhost/jxgl";  
  9.     private static String username="root";  
  10.     private static String pwd="root1234";  
  11.     static  
  12.     {  
  13.         try  
  14.         {  
  15.             if(true)  
  16.             {  
  17.                 Driver = "oracle.jdbc.driver.OracleDriver";  
  18.                 Url = "jdbc:oracle:thin:@localhost:1521:qhit";    
  19.                 username="scott";  
  20.                 pwd="tiger";  
  21.             }   
  22.             Class.forName(Driver);  
  23.         }  
  24.         catch (ClassNotFoundException e)  
  25.         {  
  26.             // TODO Auto-generated catch block  
  27.             e.printStackTrace();  
  28.         }  
  29.     }  
  30.   
  31.     public static Connection getConnection() throws Exception  
  32.     {  
  33.         return DriverManager.getConnection(Url, username, pwd);  
  34.     }  
  35.   
  36.     public static void close(ResultSet rs)  
  37.     {  
  38.         try  
  39.         {  
  40.             if (rs != null)  
  41.             {  
  42.                 rs.close();  
  43.             }  
  44.         }  
  45.         catch (SQLException e)  
  46.         {  
  47.             // TODO Auto-generated catch block  
  48.             e.printStackTrace();  
  49.         }  
  50.     }  
  51.   
  52.     public static void close(Statement pstm)  
  53.     {  
  54.         try  
  55.         {  
  56.             if (pstm != null)  
  57.             {  
  58.                 pstm.close();  
  59.             }  
  60.         }  
  61.         catch (SQLException e)  
  62.         {  
  63.             // TODO Auto-generated catch block  
  64.             e.printStackTrace();  
  65.         }  
  66.     }  
  67.   
  68.     public static void close(Connection conn)  
  69.     {  
  70.         try  
  71.         {  
  72.             if (conn != null && !conn.isClosed())  
  73.             {  
  74.                 conn.close();  
  75.             }  
  76.         }  
  77.         catch (SQLException e)  
  78.         {  
  79.             // TODO Auto-generated catch block  
  80.             e.printStackTrace();  
  81.         }  
  82.     }  
  83. }  

 

数据库反编译类:

  1. /** 
  2.  *  
  3.  * FileName:      DataBaseInfo 
  4.  * 
  5.  * FileType:      final Class 
  6.  * 
  7.  * Date:          2009年07月11日 
  8.  * 
  9.  * Author:        一点红 
  10.  *  
  11.  * Email:         CPUCPA@163.COM 
  12.  * 
  13.  * Description:   反编译数据库 
  14.  *  
  15.  */  
  16. package com.qhit.services;  
  17.   
  18. import java.sql.Connection;  
  19. import java.sql.DatabaseMetaData;  
  20. import java.sql.PreparedStatement;  
  21. import java.sql.ResultSet;  
  22. import java.sql.ResultSetMetaData;  
  23. import java.util.ArrayList;  
  24. import java.util.HashMap;  
  25. import java.util.List;  
  26. import java.util.Map;  
  27.   
  28. import com.qhit.db.DBUtils;  
  29.   
  30. public final class DataBaseInfo  
  31. {  
  32.     /** 
  33.      * 获取数据库Table列表 
  34.      * @throws Exception 
  35.      */  
  36.     public static void tableList()throws Exception  
  37.     {  
  38.         Connection conn=null;  
  39.         ResultSet rs=null;  
  40.         try  
  41.         {  
  42.             conn=DBUtils.getConnection();  
  43.             DatabaseMetaData dbmd=conn.getMetaData();  
  44.               
  45.             /** 
  46.              * 获取类别 
  47.              */  
  48.             //rs=dbmd.getCatalogs();  
  49.             /** 
  50.              * 获取模式 
  51.              */  
  52.             //rs=dbmd.getSchemas();  
  53.             /** 
  54.              * 限定获取表的类型 
  55.              */  
  56.             String types[]={"TABLE","VIEW"};  
  57.               
  58.             /** 
  59.              * MySQL获取表信息 
  60.              */  
  61.             //rs=dbmd.getTables("jxgl", null, null, types);           
  62.             /** 
  63.              * Oracle获取表信息 
  64.              */  
  65.             rs=dbmd.getTables(null, "SCOTT", null, types);  
  66.               
  67.               
  68.             /** 
  69.              * 以下部分为结果集解析 
  70.              */  
  71.             ResultSetMetaData rsmd=rs.getMetaData();  
  72.             int size=rsmd.getColumnCount();  
  73.   
  74.             List rows=new ArrayList();  
  75.             Map item=null;  
  76.             while(rs.next())  
  77.             {  
  78.                 item=new HashMap();  
  79.                 for(int i=1;i<=size;i++)  
  80.                 {  
  81.                     item.put(rsmd.getColumnName(i), rs.getString(i));  
  82.                 }  
  83.                 rows.add(item);  
  84.             }  
  85.             System.out.println(rows);  
  86.         }  
  87.         finally  
  88.         {  
  89.             DBUtils.close(rs);  
  90.             DBUtils.close(conn);  
  91.         }  
  92.     }  
  93.     public static void main(String[] args)  
  94.     {  
  95.         try  
  96.         {  
  97.             tableList();  
  98.             //tableinfo();  
  99.         }  
  100.         catch (Exception e)  
  101.         {  
  102.             // TODO Auto-generated catch block  
  103.             e.printStackTrace();  
  104.         }  
  105.     }  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值