用一段java程序实现数据从A库到B库的导入!如:
A库ip:10.0.0.1
B库ip:10.0.0.2
对这种程序大家有什么好的思路请赐教!
Java连接数据库方式:
java通过JDBC直连数据库。
以上程序只能使用java!
高手们请赐教!论坛新人,积分不多,请见谅!
A库ip:10.0.0.1
B库ip:10.0.0.2
对这种程序大家有什么好的思路请赐教!
Java连接数据库方式:
java通过JDBC直连数据库。
以上程序只能使用java!
高手们请赐教!论坛新人,积分不多,请见谅!
或者可以使用dblink(仅支持oralce,不晓得java程序能否调用他)
DatabaseMetaData 和ResultSetMetaData 很有用,但一般做开发的少用,因为我们的表结构基本上是固定了的,楼主这种不晓得结构的,才会去使用这两个类。
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 公共服务组件:数据库备份服务
* 提供将数据库中数据解析为可导入的sql服务,数据库驱动需由调用端负责加载
* 仅支持varchar/text/datetime/int/tinyint/double/boolean,其他类型需扩展
* @author:dinghun8leech
* @date:100119
* @version:1.0test
*/
public class DBDataBackUp {
private boolean isClose = false;
private boolean delete = false;
private static final String SELECT_SQL = "select * from ";
private static final String INSERT_SQL_END = ");";
private static final String DELETE_SQL = "delete from ";
private Connection con = null;
private Map<String,String> tables = new HashMap<String, String>();
private Map<String, Map<String, Integer>> columns = new HashMap<String, Map<String,Integer>>();
/**
* +3参数重载构造方法,初始化数据库备份组件
* @param String 数据库连接url
* @param String 数据库帐户
* @param String 数据库密码
* @throws SQLException 建立连接和操作数据库发生异常时抛出此异常
*/
public DBDataBackUp(String url, String user, String pwd) throws SQLException {
con = DriverManager.getConnection(url, user, pwd);
List<String> allTables = getTables();
int size = allTables.size();
for (int i=0;i<size;i++) {
String table = allTables.get(i);
columns.put(table, getColumn(table));
tables.put(table, parseInsertSql(table));
}
}
/**
* 当前数据库备份组件是否已释放资源而不可再次使用
* @return boolean 是否已关闭
*/
public boolean isClosed() {
return isClose;
}
/**
* 设置当前数据库备份组件在生成insert sql时是否自动添加用于清表的delete sql
* @param delete 是否添加自动清表语句
*/
public void addDeleteSQL(boolean delete) {
this.delete = delete;
}
/**
* 关闭此数据库备份组件所使用的连接资源
* @throws SQLException 当出现资源释放失败时抛出此异常
*/
public void close() throws SQLException {
if (con != null) {
con.close();
}
isClose = true;
}
/**
* 获取库中所有数据insert sql
* @return List<String> 库中所有数据的insert sql
*/
public List<String> parseDatabaseToSql() throws SQLException {
if (isClosed()) {
throw new SQLException("当前资源已被释放");
}
List<String> sqls = new ArrayList<String>();
int size = tables.size();
List<String> allTables = getTables();
for (int i=0;i<size;i++) {
sqls.addAll(parseTableToSql(allTables.get(i)));
}
return sqls;
}
/**
* 获取所需表的所有数据insert sql
* @param String 表名
* @return List<String> 当前表中所有数据的insert sql
*/
public List<String> parseTableToSql(String table) throws SQLException {
if (isClosed()) {
throw new SQLException("当前资源已被释放");
}
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(SELECT_SQL + table);
Map<String, Integer> thisColumnDesc = columns.get(table);
int columnSize = thisColumnDesc.size();
List<String> sqls = new ArrayList<String>();
if (delete) {
sqls.add(DELETE_SQL + table + ";");
}
while (rs.next()) {
sqls.add(parseOneRecordToSql(rs, thisColumnDesc, columnSize * 25, columnSize, tables.get(table)));
}
rs.close();
stmt.close();
return sqls;
}
/**
* 根据表名和其表结构解析insert sql语句前半部
* @param String 表名
* @return String 当前表结构对应的insert sql语句前半部
*/
private String parseInsertSql(String table) {
Map<String, Integer> columnsDesc = columns.get(table);
List<String> keys = new ArrayList<String>(columnsDesc.keySet());
int size = keys.size();
StringBuffer sb = new StringBuffer(size * 15);
sb.append("insert into ");
sb.append(table);
sb.append("(");
for (int j=0;j<size;j++) {
if (j >0) {
sb.append(",");
}
sb.append(keys.get(j));
}
sb.append(") value(");
return sb.toString();
}
/**
* 将单条数据解析为insert类型的sql语句
* @param ResultSet 确认当前指针位置的结果集对象
* @param Map<String, Integer> 当前表结构 String 字段名 Integer 类型
* @param int sql语句预计字符长度
* @param int 当前表字段数量
* @param String 与当前表结构相符的insert sql语句前半部 例 “insert into table(a,b,c) value(”
* @return String 当前指针对应数据的完整insert sql
* @throws SQLException 当发生从数据库取数据、类型解析异常或当前不支持的字段类型时抛出此异常
*/
private String parseOneRecordToSql(ResultSet rs, Map<String, Integer> columnsDesc, int bufferSize, int columnCount, String sql) throws SQLException {
List<String> keys = new ArrayList<String>(columnsDesc.keySet());
StringBuffer sb = new StringBuffer(bufferSize);
sb.append(sql);
for (int j=0;j<columnCount;j++) {
String key = keys.get(j);
if (j >0) {
sb.append(",");
}
switch (columnsDesc.get(key)) {
case -7 ://boolean
sb.append(rs.getBoolean(key));
break;
case -6 ://tinyint byte
sb.append(rs.getByte(key));
break;
case -1 ://text String
sb.append("'");
String text = rs.getString(key);
if (text != null) {
sb.append(text);
}
sb.append("'");
break;
case 4 ://int
sb.append(rs.getInt(key));
break;
case 8 ://double
sb.append(rs.getDouble(key));
break;
case 12 ://varchar String
sb.append("'");
String varchar = rs.getString(key);
if (varchar != null) {
sb.append(varchar);
}
sb.append("'");
break;
case 93 ://datetime String
String datetime = rs.getString(key);
if (datetime != null) {
sb.append("'");
sb.append(datetime);
sb.append("'");
} else {
sb.append("null");
}
break;
default :
throw new SQLException("暂无法支持的数据格式:"+columnsDesc.get(key));
}
}
sb.append(INSERT_SQL_END);
return sb.toString();
}
/**
* 获取当前库中所有表名称
* @return List<String> 当前库中所有表名称
* @throws SQLException 当发生任何数据库操作异常时抛出此异常
*/
public List<String> getTables() throws SQLException {
if (isClosed()) {
throw new SQLException("当前资源已被释放");
}
DatabaseMetaData dbmd = con.getMetaData();
List<String> tables = new ArrayList<String>();
ResultSet rs = dbmd.getTables(null, null, null, new String[]{"TABLE"});
while (rs.next()) {
String tableName = rs.getString("TABLE_NAME");
String type = rs.getString("TABLE_TYPE");
if (type.equalsIgnoreCase("table") && tableName.indexOf("$") == -1) {
tables.add(tableName);
}
}
rs.close();
return tables;
}
/**
* 获取指定表中所有字段和类型
* @param String 表名
* @return Map<String, Integer> 所有字段和类型 String 字段名 Integer 表述字段类型的int值
* @throws SQLException 当发生任何数据库操作异常时抛出此异常
*/
public Map<String,Integer> getColumn(String table) throws SQLException {
if (isClosed()) {
throw new SQLException("当前资源已被释放");
}
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(SELECT_SQL + table + " limit 0,1");
ResultSetMetaData rsmd = rs.getMetaData();
Map<String,Integer> columns = new HashMap<String,Integer>();
for (int i=1;i<=rsmd.getColumnCount();i++) {
columns.put(rsmd.getColumnName(i), rsmd.getColumnType(i));
}
rs.close();
stmt.close();
return columns;
}
}
这是我前两天写的组件,用于mysql的备份,可在指定库的情况下自己解析所有表和所有字段进行sql语句生成,需要转移数据可另起一条连接将其生成的sql语句执行即可。
问题:
1.效率不佳
2.支持字段有限(都是我常用字段,所以暂时写了这几个)
3.部分字段为空时未作周密测试,可能造成sql语句错误。