zoukankan      html  css  js  c++  java
  • DatabaseMetaData开发实务

    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

     

    view plaincopy to clipboardprint?
    package com.qhit.db;  
     
    import java.sql.*;  
     
    public class DBUtils  
    {  
        private static String Driver = "com.mysql.jdbc.Driver";  
        private static String Url = "jdbc:mysql://localhost/jxgl";  
        private static String username="root";  
        private static String pwd="root1234";  
        static 
        {  
            try 
            {  
                if(true)  
                {  
                    Driver = "oracle.jdbc.driver.OracleDriver";  
                    Url = "jdbc:oracle:thin:@localhost:1521:qhit";    
                    username="scott";  
                    pwd="tiger";  
                }   
                Class.forName(Driver);  
            }  
            catch (ClassNotFoundException e)  
            {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
        }  
     
        public static Connection getConnection() throws Exception  
        {  
            return DriverManager.getConnection(Url, username, pwd);  
        }  
     
        public static void close(ResultSet rs)  
        {  
            try 
            {  
                if (rs != null)  
                {  
                    rs.close();  
                }  
            }  
            catch (SQLException e)  
            {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
        }  
     
        public static void close(Statement pstm)  
        {  
            try 
            {  
                if (pstm != null)  
                {  
                    pstm.close();  
                }  
            }  
            catch (SQLException e)  
            {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
        }  
     
        public static void close(Connection conn)  
        {  
            try 
            {  
                if (conn != null && !conn.isClosed())  
                {  
                    conn.close();  
                }  
            }  
            catch (SQLException e)  
            {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
        }  

    package com.qhit.db;

    import java.sql.*;

    public class DBUtils
    {
     private static String Driver = "com.mysql.jdbc.Driver";
     private static String Url = "jdbc:mysql://localhost/jxgl";
     private static String username="root";
     private static String pwd="root1234";
     static
     {
      try
      {
       if(true)
       {
        Driver = "oracle.jdbc.driver.OracleDriver";
        Url = "jdbc:oracle:thin:@localhost:1521:qhit"; 
        username="scott";
        pwd="tiger";
       }
       Class.forName(Driver);
      }
      catch (ClassNotFoundException e)
      {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
     }

     public static Connection getConnection() throws Exception
     {
      return DriverManager.getConnection(Url, username, pwd);
     }

     public static void close(ResultSet rs)
     {
      try
      {
       if (rs != null)
       {
        rs.close();
       }
      }
      catch (SQLException e)
      {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
     }

     public static void close(Statement pstm)
     {
      try
      {
       if (pstm != null)
       {
        pstm.close();
       }
      }
      catch (SQLException e)
      {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
     }

     public static void close(Connection conn)
     {
      try
      {
       if (conn != null && !conn.isClosed())
       {
        conn.close();
       }
      }
      catch (SQLException e)
      {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
     }
    }


     

    数据库反编译类:

    view plaincopy to clipboardprint?
    /** 
     *  
     * FileName:      DataBaseInfo 
     * 
     * FileType:      final Class 
     * 
     * Date:          2009年07月11日 
     * 
     * Author:        一点红 
     *  
     * Email:        
    CPUCPA@163.COM 
     * 
     * Description:   反编译数据库 
     *  
     */ 
    package com.qhit.services;  
     
    import java.sql.Connection;  
    import java.sql.DatabaseMetaData;  
    import java.sql.PreparedStatement;  
    import java.sql.ResultSet;  
    import java.sql.ResultSetMetaData;  
    import java.util.ArrayList;  
    import java.util.HashMap;  
    import java.util.List;  
    import java.util.Map;  
     
    import com.qhit.db.DBUtils;  
     
    public final class DataBaseInfo  
    {  
        /** 
         * 获取数据库Table列表 
         * @throws Exception 
         */ 
        public static void tableList()throws Exception  
        {  
            Connection conn=null;  
            ResultSet rs=null;  
            try 
            {  
                conn=DBUtils.getConnection();  
                DatabaseMetaData dbmd=conn.getMetaData();  
                  
                /** 
                 * 获取类别 
                 */ 
                //rs=dbmd.getCatalogs();  
                /** 
                 * 获取模式 
                 */ 
                //rs=dbmd.getSchemas();  
                /** 
                 * 限定获取表的类型 
                 */ 
                String types[]={"TABLE","VIEW"};  
                  
                /** 
                 * MySQL获取表信息 
                 */ 
                //rs=dbmd.getTables("jxgl", null, null, types);           
                /** 
                 * Oracle获取表信息 
                 */ 
                rs=dbmd.getTables(null, "SCOTT", null, types);  
                  
                  
                /** 
                 * 以下部分为结果集解析 
                 */ 
                ResultSetMetaData rsmd=rs.getMetaData();  
                int size=rsmd.getColumnCount();  
     
                List rows=new ArrayList();  
                Map item=null;  
                while(rs.next())  
                {  
                    item=new HashMap();  
                    for(int i=1;i<=size;i++)  
                    {  
                        item.put(rsmd.getColumnName(i), rs.getString(i));  
                    }  
                    rows.add(item);  
                }  
                System.out.println(rows);  
            }  
            finally 
            {  
                DBUtils.close(rs);  
                DBUtils.close(conn);  
            }  
        }  
        public static void main(String[] args)  
        {  
            try 
            {  
                tableList();  
                //tableinfo();  
            }  
            catch (Exception e)  
            {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
        }  

  • 相关阅读:
    JSOI2018 战争(凸包+闵可夫斯基和)
    树结构
    Emacs奇技淫巧
    概率期望
    动态DP
    无旋treap大法好
    玩NOILinux
    <虚树+树型DP> HNOI2014世界树
    <虚树+树型DP> SDOI2011消耗战
    日志系统升级之路(.Net客户端的使用)
  • 原文地址:https://www.cnblogs.com/zailushang117/p/3714772.html
Copyright © 2011-2022 走看看