记用JDBC合并数据库表数据工具问题解决

实现过程(要合并的两个表结构要一致)

首先获取两个数据库连接

/**
     * 获取数据库链接
     */
    private String getSqlServiceConnIn(LhdbCfgConn lhdbCfgConn) {
        String connDriverIn = "oracle.jdbc.driver.OracleDriver";
        String connInUser = "user1";
        String connInPw ="12345678";
        String url ="jdbc:oracle:thin:@localhost:1521:orcl" ;
        try {
            Class.forName(connDriverIn).newInstance();
            connectionIn = DriverManager.getConnection(url, connInUser,
                    connInPw);// 打开conn
            System.out.println(connectionIn + "-----------sqlServiceConn=" + url);
            return "ok";
        } catch (Exception e) {

            connectionIn = null;
            e.printStackTrace();
            System.out.println("获取in数据库链接异常");
            return "获取被同步的数据库链接异常";
        }
    }
/**
     * 获取数据库链接
     */
    private String getSqlServiceConnOut(LhdbCfgConn lhdbCfgConn) {
        String connDriverOut = "oracle.jdbc.driver.OracleDriver";
        String connOutUser = "user2";
        String connOutPw = "12345678";
        String url = lhdbCfgConn.getConnOutLink();
        try {
            Class.forName(connDriverOut).newInstance();
            connectionOut = DriverManager.getConnection(url, connOutUser,
                    connOutPw);// 打开conn
            System.out.println(connectionOut + "-----------sqlServiceConn=" + url);
            // 设置自动提交为false
            connectionOut.setAutoCommit(false);
            return "ok";
        } catch (Exception e) {

            connectionOut = null;
            e.printStackTrace();
            System.out.println("获取out数据库链接异常");
            return "获取被同步的数据库链接异常";
        }
    }

注意:为了后边利用事务和批量提交,要把要写入的数据库连接的自动提交设置为false,connectionOut.setAutoCommit(false);

查询表数据

private ResultSet getResultSet() throws SQLException {
        if(connectionIn==null){
           //这里要获取连接
        }
        String tableName = "表名";
        Timestamp timestamp = 最后更新时间;
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("select * from ").append(tableName);
        if (timestamp != null) {
            stringBuilder.append(" where update > ? and update<= ?");
        }
        String qureSql = stringBuilder.toString();
        logger.error("quersql==" + qureSql);
        logTxt("quersql==" + qureSql);
        statementIn = connectionIn.prepareStatement(qureSql, ResultSet.TYPE_FORWARD_ONLY,
                ResultSet.CONCUR_READ_ONLY);
        Timestamp timestamp1 = UtilDate.currentTimestamp();
        if (timestamp != null) {
            statementIn.setTimestamp(1,timestamp);
            statementIn.setTimestamp(2,timestamp1);
        }
        statementIn.setFetchSize(10000);//设置每次读取的数量
        ResultSet rsIn = statementIn.executeQuery();
        return rsIn;
    }

注意:在测试过程种遇到一个170w条数据的表,每到40w左右的时候就报内存溢出,开始总是以为内存设置不够大,设置为4G,6G,8G改善情况不大,通过日志看出,是读取的时候报错,猜测是因为读取数据太多导致内存溢出,一顿度娘,在api中有设置每次返回行数限制(statementIn.setFetchSize(10000)),每次返回固定行数,减少内存消耗.

获取表中含有哪些字段

/**
     * 获取字段
     *
     * @param rs
     * @throws SQLException
     */
    private List<String> getColumns(ResultSet rs) throws SQLException {
        ResultSetMetaData data = rs.getMetaData();
        List<String> list = new ArrayList<>();
        for (int i = 1; i <= data.getColumnCount(); i++) {
            // 获得所有列的数目及实际列数
            //int columnCount = data.getColumnCount();
            // 获得指定列的列名
            String columnName = data.getColumnName(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("获得列" + 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);*/

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

            list.add(columnName);
        }

        return list;
    }

根据获取的字段合成insert语句

/**
     * @param list
     * @param tableName
     * @return
     */
    private String getsql(List<String> list, String tableName) {
        int size = list == null ? 0 : list.size();
        StringBuffer sbSql = new StringBuffer();
        StringBuffer sbColumns = new StringBuffer();
        StringBuffer sbValue = new StringBuffer();
        sbSql.append("INSERT INTO ").append(tableName).append(" ( ");
        for (int i = 0; i < size; i++) {
            String columnName = list.get(i);
            if (i == size - 1) {
                sbColumns.append(columnName);
                sbValue.append("?");
            } else {
                sbColumns.append(columnName).append(",");
                sbValue.append("?").append(",");
            }
        }
        sbSql.append(sbColumns).append(" ) VALUES ( ").append(sbValue).append(")");
        return sbSql.toString();
    }

写入数据

private void saveData(ResultSet rsIn, String outTableName) throws SQLException {
        List<String> columns = getColumns(rsIn);
        String sql = getsql(columns, outTableName);
        int size = columns.size() + 1;

        int ttt = 0;
        logger.error("插入sql==" + sql);
        logTxt("插入sql==" + sql);
        statementOut = connectionOut.prepareStatement(sql);
        while (rsIn.next()) {
            ttt++;
            for (int i = 1; i < size; i++) {
                // 设置占位符的值
                statementOut.setObject(i, rsIn.getObject(i));
            }
            // 添加到批处理
            statementOut.addBatch();
            // 达到批量保存大小时,执行批处理
            if (ttt % 10000 == 0) {
                statementOut.executeBatch();
                statementOut.clearBatch();
                // 提交事务
                connectionOut.commit();
            }
        }
        // 执行剩余的批处理
        statementOut.executeBatch();
        // 提交事务
        connectionOut.commit();

    }

关闭连接

private void closeStatement() {
        // 关闭连接
        if (statementOut != null) {
            try {

                statementOut.clearBatch();
                statementOut.close();
                statementOut = null;
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        // 关闭连接
        if (statementIn != null) {
            try {
                statementIn.clearBatch();
                statementIn.close();
                statementIn = null;
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

日常记录
互相交流
欢迎指教
各显神通

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值