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();
}
}
}
DatabaseMetaData开发实务的更多相关文章
- UML造型——使用EA时序图工具的开发实践和经验
Enterprise Architect watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGlhb3l3NzE=/font/5a6L5L2T/fontsiz ...
- vue.js 第五课
计算属性 1.基础例子 2.计算属性 vs $watch 3.计算 setter 4.计算属性开发实务demo 1.计算属性 computed( 电脑computer) (区别普通属性) 计算属性 ...
- [最新原创电子书]lazarus开发者入门及中级教程
目前市面上没有任何一本完整的书,介绍Lazarus,Firebird这两个优秀的开发工具,同时还有一个作为他们之间桥梁的开发套件ZeosDBO,也没有任何完整的中文开发指南,本书以这三种开发套件为主线 ...
- 吐血整理 Delphi系列书籍 118本(全)
Delphi 教程 系列书籍 网友(老帅)整理 001_<Delhpi6数据库设计思想与实践> 002_<Delphi6应用开发指南> 003_<Delphi6开发人员指 ...
- AES128和AES256主要区别和安全程度是多少?他们对于机器的消耗是怎样的?两者性能如何?实际开发如何选择?
高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标准用来替代原先的DES, ...
- 【转】web开发需要知道的事情
在StackExchange上有人问了这样一个问题:What should every programmer know about web development?(关于Web开发,什么是所有程序员需 ...
- Web开发中需要了解的东西
在StackExchange上有人问了这样一个问题:What should every programmer know about web development?(关于Web开发,什么是所有程序员需 ...
- 深圳市共创力推出独家课程《AHB和OSG》高级实务培训课程!
<AHB和OSG>高级实务培训课程大纲 [适合对象]:高层管理者.产品经理.资源经理.各专项经理.研发等部门的负责人和骨干员工. [课程受益]:高层如何对项目的优先级进行排序和资源分配. ...
- odoo11新开发功能模块测试指南
根据实际业务需要,我们开发了一些生产实务中一些功能模块,作为制造行业管理信息化解决方案的基础,并应部分客户需求,做了测试系统,现将测试方式公布如下: 一.测试环境 服务器地址 http://106.1 ...
随机推荐
- Python的filter与map内置函数
简单的记录下这两个函数的功能: list(filter(lambda x : x % 2, range(10))) 上例是返回了0-10之间的所有基数组成的列表.filter()有2个参数,第一个参数 ...
- Android App退出检测
app的退出检测是很难的,但是获取app“要退出”的状态就容易多了,退出的瞬间并不是真的退出了,ActivityManager要销毁activity,也需要一些时间和资源的. 先见下面的运行效果: ...
- android反编译查看源码,apk解压后XML乱码解决
1:找了好几个软件都不能图形化的解决反编译,很不舒服,最后找了个还算顺手的,顺便保存下. 2:使用过程 <1> apk转jar apktoolkit工具 <2> 查看jar源码 ...
- c++ windows与linux通信中文乱码问题解决方法
在linux中默认编码方式是UTF-8,在Windows下默认编码方式时GB2312.因此,在Windows和Linux进行通信的时候,如果没有进行转码则会出现乱码问题.因此,需要进行UTF-8和GB ...
- 三维点集拟合:平面拟合、RANSAC、ICP算法
ACM算法分类:http://www.kuqin.com/algorithm/20080229/4071.html 一: 拟合一个平面:使用SVD分解,代码里面去找吧 空间平面方程的一般表达式为: A ...
- eclipse的小技巧
Eclipse 保存文件时自动格式化代码 很多同学不知道Eclipse有个很有用的功能,就是自动格式源代码的功能,一般大家都是直接Ctrl+Shift+F手动格式化,多浪费时间. 其实Eclipse里 ...
- python的小数据池和深浅拷贝
小数据池 一种数据缓存机制,也称驻留机制 在同一代码块,相同的值不会开辟新的内存 特殊字符除外 小数据池只针对:在控制台时! 数字 :-5到256间的整数会被缓存 布尔值:都会缓存8 字符串 小于等于 ...
- ojdbc14:11.2.0.1.0出错
首先在相关目录下找到你的ojdbc14的包:比如 我的出错问题:(之前是11.2.0.1.0,后改为10.2.0.1.0) 我的包路径:C:\my_java\maven_repository\com\ ...
- Flask-SQLAlchemy中解决数据库连接1366报错
报错信息:Warning: (1366, "Incorrect string value: '\\xD6\\xD0\\xB9\\xFA\\xB1\\xEA...' for column 'V ...
- hive 自定义函数(udf)
1.解压hive的压缩包 2.新建java项目,将hive压缩包里面lib文件夹的jar包导入新建的项目 3.编写java程序 package udfdemo; import org.apache.h ...