用一段java程序实现数据从A库到B库的导入!如:
A库ip:10.0.0.1
B库ip:10.0.0.2
对这种程序大家有什么好的思路请赐教!
Java连接数据库方式:
java通过JDBC直连数据库。
以上程序只能使用java!
高手们请赐教!论坛新人,积分不多,请见谅!

解决方案 »

  1.   

    建两个数据源,使用批处理完成,
    或者可以使用dblink(仅支持oralce,不晓得java程序能否调用他)
      

  2.   

    前几天好象有人问过。如果是学生的作业的话,应该是老师想让你知道 DatabaseMetaData 和 ResultSetMetaData 的使用。可以从 java.sql.Connection.getMetaData 及 java.sql.getMetaData 得到。如果是工程师的话,应该从工程与应用角度出发,使用现成的商业数据迁移工具。
      

  3.   

    http://canofy.javaeye.com/blog/300661
      

  4.   

    有什么问题?  搞2个datasource 不就可以了
      

  5.   

    嗯,同意。
    DatabaseMetaData 和ResultSetMetaData 很有用,但一般做开发的少用,因为我们的表结构基本上是固定了的,楼主这种不晓得结构的,才会去使用这两个类。
      

  6.   

    package com.xxx.common;
    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语句错误。