mysql备份数据库 jdbc,透过jdbc实现Oracle备份到Mysql

一直用的系统是 Oracle的数据库,现在一个客户比较小,不想投入钱购买数据库软件,所以只能使用Mysql,需要将框架中的一些表结构、记录从Oracle导入到Mysql中去。网上没找到好用的软件,所以决定自己弄一个小程序实现异构库备份:

思路比较简单, 先生成建表语句并在mysql库中执行,在生成insert语句在mysql中执行。

一:生成建表语句重点是需要获取表的字段,默认值,是否为空, 字段类型、字段长度等, 万幸的是这些jdbc都有实现,通过Connect获取数据库的DatabaseMetaData--dmd,

System.out.println("加载Oracle链接0...");

connect = connect(0);

System.out.println("加载Mysql链接1...");

insertConnect = connect(1);

System.out.println("获取dmd...");

dmd = connect.getMetaData();

再通过DatabaseMetaData--dmd查询表单字段信息,

ResultSet colrs = dmd.getColumns("%", dmd.getUserName(),table.toUpperCase(), "%");

然后解析获取到的ResultSet信息后即可获取到字段的全部信息,生成建表语句:

二:取生成insert语句类似,需要适用select语句查询表的信息,然后循环解析每一行的记录,生成insert插入,此处执行sql的是PreparedStatement,可以循环适用insert语句,仅需要改变每一次动态设置的值属性即可。

全部代码比较简单,直接上代码:

有两个类:jdbc工具类:JDBCUtil.java

import java.sql.Connection;

import java.sql.DatabaseMetaData;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.ResultSetMetaData;

import java.sql.SQLException;

import java.util.ArrayList;

import java.util.List;

public class JDBCUtil {

public static Connection connect(int type) {

Connection conn;

if (type == 0) {//oracle

conn = connectOracle();

} else {//Mysql

conn = connectMysql();

}

return conn;

}

/**

* 连接Oracle

*

* @return

*/

public static Connection connectMysql() {

// 连接MySql数据库,用户名和密码

String username = "111212";

String password = "2121";

String url = "jdbc:mysql://192.168.1.1/training?user=" + username+ "&password=" + password + "";

Connection conn = null;

try {

// 加载MySql的驱动类

Class.forName("com.mysql.jdbc.Driver");

conn = DriverManager.getConnection(url);

} catch (ClassNotFoundException e) {

System.out.println("找不到驱动程序类 ,加载驱动失败!");

e.printStackTrace();

} catch (SQLException se) {

System.out.println("数据库连接失败!");

se.printStackTrace();

}

return conn;

}

/**

* 连接Oracle

*

* @return

*/

public static Connection connectOracle() {

String url = "jdbc:oracle:thin:@192.168.1.1:1521:orcl";

// 连接MySql数据库,用户名和密码都是root

String username = "abcaf";

String password = "syjgagagac";

Connection conn = null;

try {

// 加载MySql的驱动类

Class.forName("oracle.jdbc.OracleDriver");

conn = DriverManager.getConnection(url, username, password);

} catch (ClassNotFoundException e) {

System.out.println("找不到驱动程序类 ,加载驱动失败!");

e.printStackTrace();

} catch (SQLException se) {

System.out.println("数据库连接失败!");

se.printStackTrace();

}

return conn;

}

public static List getColumnNames(ResultSetMetaData meta) throws SQLException{

List list = new ArrayList();

for (int i = 1; i <= meta.getColumnCount(); i++) {

list.add(meta.getColumnName(i));

}

return list;

}

// ResultSetMetaData 使用示例

// 此方法参考 http://blog.csdn.net/yirentianran/article/details/2950321

public static void demoResultSetMetaData(ResultSetMetaData data)

throws SQLException {

for (int i = 1; i <= data.getColumnCount(); i++) {

// 获得所有列的数目及实际列数

int columnCount = data.getColumnCount();

// 获得指定列的列名

String columnName = data.getColumnName(i);

// 获得指定列的列值

// String columnValue = rs.getString(i);

// 获得指定列的数据类型

int columnType = data.getColumnType(i);

// 获得指定列的数据类型名

String columnTypeName = data.getColumnTypeName(i);

// 所在的Catalog名字

String catalogName = data.getCatalogName(i);

// 对应数据类型的类

String columnClassName = data.getColumnClassName(i);

// 在数据库中类型的最大字符个数

int columnDisplaySize = data.getColumnDisplaySize(i);

// 默认的列的标题

String columnLabel = data.getColumnLabel(i);

// 获得列的模式

String schemaName = data.getSchemaName(i);

// 某列类型的精确度(类型的长度)

int precision = data.getPrecision(i);

// 小数点后的位数

int scale = data.getScale(i);

// 获取某列对应的表名

String tableName = data.getTableName(i);

// 是否自动递增

boolean isAutoInctement = data.isAutoIncrement(i);

// 在数据库中是否为货币型

boolean isCurrency = data.isCurrency(i);

// 是否为空

int isNullable = data.isNullable(i);

// 是否为只读

boolean isReadOnly = data.isReadOnly(i);

// 能否出现在where中

boolean isSearchable = data.isSearchable(i);

System.out.println(columnCount);

System.out.println("获得列" + i + "的字段名称:" + columnName);

// System.out.println("获得列" + i + "的字段值:" + columnValue);

System.out.println("获得列" + i + "的类型,返回SqlType中的编号:" + columnType);

System.out.println("获得列" + i + "的数据类型名:" + columnTypeName);

System.out.println("获得列" + i + "所在的Catalog名字:" + catalogName);

System.out.println("获得列" + i + "对应数据类型的类:" + columnClassName);

System.out.println("获得列" + i + "在数据库中类型的最大字符个数:"

+ columnDisplaySize);

System.out.println("获得列" + i + "的默认的列的标题:" + columnLabel);

System.out.println("获得列" + i + "的模式:" + schemaName);

System.out.println("获得列" + i + "类型的精确度(类型的长度):" + precision);

System.out.println("获得列" + i + "小数点后的位数:" + scale);

System.out.println("获得列" + i + "对应的表名:" + tableName);

System.out.println("获得列" + i + "是否自动递增:" + isAutoInctement);

System.out.println("获得列" + i + "在数据库中是否为货币型:" + isCurrency);

System.out.println("获得列" + i + "是否为空:" + isNullable);

System.out.println("获得列" + i + "是否为只读:" + isReadOnly);

System.out.println("获得列" + i + "能否出现在where中:" + isSearchable);

}

}

// 演示 DatabaseMetaData

public static void demoDatabaseMetaData() {

try {

Connection con = connect(0);

//

DatabaseMetaData dmd = con.getMetaData();

System.out.println("当前数据库是:" + dmd.getDatabaseProductName());

System.out.println("当前数据库版本:" + dmd.getDatabaseProductVersion());

System.out.println("当前数据库驱动:" + dmd.getDriverVersion());

System.out.println("当前数据库URL:" + dmd.getURL());

System.out.println("当前数据库是否是只读模式?:" + dmd.isReadOnly());

System.out.println("当前数据库是否支持批量更新?:" + dmd.supportsBatchUpdates());

System.out .println("当前数据库是否支持结果集的双向移动(数据库数据变动不在ResultSet体现)?:" + dmd.supportsResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE));

System.out .println("当前数据库是否支持结果集的双向移动(数据库数据变动会影响到ResultSet的内容)?:" + dmd.supportsResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE));

System.out.println("========================================");

// ResultSet rs = dmd.getTables(null, null, "%", null);

// System.out.println("表名" + "," + "表类型");

/*

* while (rs.next()) { String tname =

* rs.getString("TABLE_NAME").toLowerCase();

* if(!tname.startsWith("t_")){ continue; }

* System.out.println(rs.getString("TABLE_NAME") + ","+

* rs.getString("TABLE_TYPE")); }

*/

System.out.println("========================================");

ResultSet rs = dmd.getPrimaryKeys(null, "SYJC", "t_mz_djlr".toUpperCase());

while (rs.next()) {

System.out .println(rs.getString(3) + "表的主键是:" + rs.getString(4));

}

System.out.println("========================================");

rs = dmd.getColumns("%", "SYJC", "t_mz_djlr", "%");

System.out.println("t_student表包含的字段:");

while (rs.next()) {

System.out.println(rs.getString(4) + " " + rs.getString(6) + "(" + rs.getString(7) + ");");

}

System.out.println("========================================");

} catch (Exception e) {

System.out.println("数据库操作出现异常");

}

}

}

还有一个实现 解析字段信息生成建表语句、解析结果生成insert语句的类DBBackUtil.java

import java.sql.Connection;

import java.sql.DatabaseMetaData;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.ResultSetMetaData;

import java.sql.SQLException;

import java.sql.Statement;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

public class DBBackUtil extends JDBCUtil{

public static Connection connect;

public static Connection insertConnect;

public static DatabaseMetaData dmd;

public static Map dataTypesMap = new HashMap();

public static List types = new ArrayList();

public static Map unneedLength = new HashMap();

static{

/**

* 此处对象的是 jdbcType 将要转换到mysql的数据类型

*/

dataTypesMap.put(12+"","VARCHAR");

dataTypesMap.put(3+"","DECIMAL");

dataTypesMap.put(93+"","TIMESTAMP");

dataTypesMap.put(1+"","CHAR");

dataTypesMap.put(6+"","DECIMAL");

dataTypesMap.put(2005+"","LONGTEXT");

dataTypesMap.put(1111+"","VARCHAR");

/***不需要长度的字段, clob(longtext)、TIMESTAMP*/

unneedLength.put(93+"",true);

unneedLength.put(2005+"",true);

types.add("VARCHAR2");

types.add("NUMBER");

types.add("DATE");

types.add("CHAR");

types.add("FLOAT");

types.add("CLOB");

types.add("NCHAR");

}

public static void main(String[] args) throws SQLException {

System.out.println("加载Oracle链接0...");

connect = connect(0);

System.out.println("加载Mysql链接1...");

insertConnect = connect(1);

System.out.println("获取dmd...");

dmd = connect.getMetaData();

String[] tables = { "t_base_zg" };

String table = null;

for (int j = 0; j < tables.length; j++) {

table = tables[j];

System.out.println("===========================================================");

createCreateSQL(table);

System.out.println("===========================================================");

System.out.println("插入开始表:"+table);

createInsertSQL(table);

System.out.println("插入表结束:"+table);

System.out.println("===========================================================");

}

//System.out.println("*******************************************");

//for (String ty : types) {

//System.out.println(ty);

//}

//System.out.println("*******************************************");

connect.close();

}

private static void createInsertSQL(String table) throws SQLException {

Statement stmt = createStmt(connect);

String sql = "select * from "+table;

System.out.println("查询表数据 "+table);

ResultSet rs = stmt.executeQuery(sql);

System.out.println("获取表字段。。。。"+table);

List columns = getColumnNames(rs.getMetaData());

StringBuffer insertSql = new StringBuffer("INSERT INTO "+table+"(");

for (String col : columns) {

insertSql.append(col+",");

}

insertSql.delete(insertSql.length()-1, insertSql.length());

insertSql.append(") \n values(");

for (String col : columns) {

insertSql.append("?,");

}

insertSql.delete(insertSql.length()-1, insertSql.length());

insertSql.append(")");

System.out.println(insertSql.toString());

System.out.println("循环插入数据......");

PreparedStatement preStmt = null;

while(rs.next()){

preStmt = createPreStmt(insertConnect, insertSql.toString());

//循环结果集 执行插入操作

for (int i = 0; i < columns.size(); i++) {

Object obj = rs.getObject(columns.get(i));

//System.out.println(obj+"\t"+(obj!=null?obj.getClass():""));

preStmt.setObject(i+1, obj);

}

int count = preStmt.executeUpdate();

System.out.println("插入 "+count+"条");

preStmt.clearBatch();

preStmt.clearParameters();

preStmt.close();

}

rs.close();

}

/**

* 生成建表语句

* @param table

* @return

* @throws SQLException

*/

public static String createCreateSQL(String table) throws SQLException{

ResultSet colrs = dmd.getColumns("%", dmd.getUserName(),table.toUpperCase(), "%");

StringBuffer sb = new StringBuffer("create table " + table + "(\n");

System.out.println("获取表 【"+table+"】的字段创建按create语句");

while (colrs.next()) {

String columnName = colrs.getString("COLUMN_NAME");//字段名

int dataType = colrs.getInt("DATA_TYPE");//数据类型 数字表示

String dataTypeName = (String) dataTypesMap.get(dataType+"");

String typeName = colrs.getString("TYPE_NAME");//类型名varchar2等,数据库的实际字段类型

if(!types.contains(typeName)){

types.add(typeName);

}

int columnSize = colrs.getInt("COLUMN_SIZE");

String remarks = colrs.getString("REMARKS");

int nullable = colrs.getInt("NULLABLE");

String columnDef = colrs.getString("COLUMN_DEF");

sb.append("\t"+columnName.toLowerCase()+"\t");//字段名

if( columnSize == 4000 && "VARCHAR".equals(dataTypeName)){

sb.append("Text");//daatype

}else{

sb.append(dataTypeName);//daatype

}

Boolean unNeedLength = unneedLength.get(dataType+"");

if(!(unNeedLength!=null && unNeedLength.booleanValue())){

if("DECIMAL".equals(dataTypeName)){

sb.append("("+(columnSize>10?10:columnSize));//字段长度

}else{

sb.append("("+columnSize);//字段长度

}

sb.append(")");

}

sb.append("\t");

//sb.append("typeName:"+typeName+"\t");

//sb.append("dataType:"+dataType+"\t");

if(columnDef!=null && !"".equals(columnDef.trim())){

sb.append("default "+columnDef+" \t"); //默认值

}

//sb.append("remarks:"+remarks+"\t");

sb.append((nullable == 0 ? " not null " : "")+","); //是否为空

sb.append("\n");

}

//去掉最后的逗号

sb.replace(sb.length()-3, sb.length(), "");

System.out.println("获取表 【"+table+"】的主键....");

/**

* 生成主键

*/

String keySql = createKeySqlByTableName(table);

if(keySql!=null && keySql.length()>0){

sb.append(",\n");

sb.append("\t"+keySql+"\n");

}

sb.append(") ENGINE=INNODB ;");

System.out.println(sb.toString());

Statement stmt = createStmt(insertConnect);

System.out.println("执行表 【"+table+"】的建表语句 ....");

boolean runRs = stmt.execute(sb.toString());

System.out.println("上述建表语句 执行完成");

return sb.toString();

}

/**

* 获取表主键集合

* @return

* @throws SQLException

*/

private static List getTableKeys(String tableName) throws SQLException{

ResultSet rs = dmd.getPrimaryKeys(null, "SYJC", tableName.toUpperCase());//此处旭要将表名设置成大写 oracle 只认大写

List list = new ArrayList();

while (rs.next()) {

list.add(rs.getString(4).toLowerCase());

}

rs.close();

return list;

}

/**

* 将表名拼接成Key sql

* @param tableName

* @return

* @throws SQLException

*/

public static String createKeySqlByTableName(String tableName) throws SQLException{

List list = getTableKeys(tableName);

return createKeySql(list);

}

/**

* 将字段拼接成Key sql

* @param list

* @return

*/

public static String createKeySql(List list){

if(list==null || list.size()<=0){

return null;

}

StringBuffer keySql = new StringBuffer();

keySql.append("primary key (");

for (int i = 0; i < list.size(); i++) {

if(i!=0 ){

keySql.append(",");

}

keySql.append(list.get(i));

}

keySql.append(")");

return keySql.toString();

}

public static PreparedStatement createPreStmt(Connection conn, String sql) {

PreparedStatement pstmt = null;

try {

pstmt = conn.prepareStatement(sql);

} catch (SQLException e) {

System.out.println("生成预处理stmt失败");

e.printStackTrace();

}

return pstmt;

}

public static Statement createStmt(Connection conn) {

Statement pstmt = null;

try {

pstmt = conn.createStatement();

} catch (SQLException e) {

System.out.println("生成预处理stmt失败");

e.printStackTrace();

}

return pstmt;

}

/**

* 解析ResultSet的单条记录,不进行 ResultSet 的next移动处理

*

* @param rs

* @return

*/

private static Map parseResultSetToMap(ResultSet rs) {

//

if (null == rs) {

return null;

}

//

Map map = new HashMap();

//

try {

ResultSetMetaData meta = rs.getMetaData();

//

int colNum = meta.getColumnCount();

//

for (int i = 1; i <= colNum; i++) {

// 列名

String name = meta.getColumnLabel(i); // i+1

Object value = rs.getObject(i);

// 加入属性

map.put(name, value);

}

} catch (SQLException e) {

e.printStackTrace();

}

//

return map;

}

///**

// * varchar2 number date char clob nchar

// *

// * @return

// */

//public static Map createMappingRelation() {

//Map map = new HashMap();

//map.put("varchar2", "varchar");

//map.put("number", "varchar");

//map.put("date", "datetime");

//map.put("char", "charo");

//map.put("clob", "mediumtext");

//map.put("nchar", "varchar");

//return map;

//}

}

通过dmd 获取字段信息 请参考:http://blog.sina.com.cn/s/blog_707a9f0601014y1y.html

转载请注明出处:http://314649444.iteye.com/admin/blogs/2307007

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值