JDBC 数据处理 总结

       以下是JDBC批处理的例子,还有处理数据的一些总结。(在公司把MySql数据库几千万的数据导入搜索Elasticsearch里面)

一、功能描述

 

二、细节考虑

2.1 为什么使用PreparedStatement进行处理?

  1、PreparedStatement接口继承Statement,PreparedStatement实例包含已编译的SQL语句,所以其执行速度要快于Statement 对象。

  2、PreparedStatement支持占位符,提高了安全性,它防止了sql语句的注入(实际处理数据时候,如果商品名称有单引号,不使用PreparedSatement会报错!)

  3、PreparedStatement代码的可读性和可维护性较好.

2.2 分页查询和Result游标进行查询有什么区别?

       分页查询是每次去数据库查询一批结果回来,进行处理,如此循环,每次循环都要建立数据库连接;Result游标也是每次去数据库取一部分结果回来(Oracle默认是10条,MySql也支持),但是只需要打开一个连接,持续使用;如果数据量很大,通信速度很快,使用游标进行数据查询。

2.3 MySql JDBC怎么实现Result游标?

  1、当statement设置以下属性时,采用的是流数据接收方式,每次只从服务器接收部份数据,直到所有数据处理完毕,不会发生JVM OOM。

          setResultSetType(ResultSet.TYPE_FORWARD_ONLY);

          setFetchSize(Integer.MIN_VALUE); 

  2、调用statement的enableStreamingResults方法,实际上enableStreamingResults方法内部封装的就是第1种方式。

  3、设置连接属性useCursorFetch=true (5.0版驱动开始支持),statement以TYPE_FORWARD_ONLY打开,再设置fetch size参数,表示采用服务器端游标,每次从服务器取fetch_size条数据。

三、代码

地址:https://github.com/huangchanghuan/CouponsUtil

  3.1  JDBC批处理MySql数据

    public static long importData( ){
        String url = "jdbc:mysql://192.168.0.183:3306/couponsdb?user=root&password=" +
                "Sunstar123!&useUnicode=true&characterEncoding=UTF-8";
        String sql = "SELECT a.classid,a.spname,a.sppic,0,0,1,b.value_id,a.id FROM " +
                "ss_hj_search_result a LEFT JOIN ss_hj_value b ON (a.brand_name = b.value_name " +
                "AND b.quantity_id = 1) WHERE a.id not in (select autoid from ss_hj_product_relation)";
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e1) {
            e1.printStackTrace();
        }
        long allStart = System.currentTimeMillis();
        long count =0;
        Connection con = null;
        Connection con1 = null;
        PreparedStatement psHJSearchResult = null;
        PreparedStatement psHJProduct = null;
        PreparedStatement psHJProductPicture = null;
        PreparedStatement psHJProductRelation = null;
        ResultSet rs = null;
        int productId=572457;
        int pictureId=1711669;
        int relationId=252381;
        try {
            //查询操作创建连接(这个连接单独用来查询,游标需要保持连接不断开)
            con = DriverManager.getConnection(url);
            con.setAutoCommit(false);
            psHJSearchResult = con.prepareStatement(sql,ResultSet.TYPE_FORWARD_ONLY,
                    ResultSet.CONCUR_READ_ONLY);
            psHJSearchResult.setFetchSize(1);
            psHJSearchResult.setFetchDirection(ResultSet.FETCH_REVERSE);
            rs = psHJSearchResult.executeQuery();
            // 写入操作创建连接
            con1 = DriverManager.getConnection(url);
            con1.setAutoCommit(false);
            //插入ss_hj_product
            psHJProduct = con1.prepareStatement("insert into ss_hj_product" +
                    "(PRODUCT_ID,CLS_ID,PRODUCT_NAME,MAIN_PICTURE,SALES_VOLUME," +
                    "COMMENTS_NUMBER,STS,PRIORITY,BRAND_ID) values(?,?,?,?,?,?,?,?,?)");
            //插入ss_hj_product_picture
            psHJProductPicture = con1.prepareStatement("insert into ss_hj_product_picture" +
                    "(PRODUCT_ID,PRODUCT_URL,PRODUCT_VIEW_URL,PICTURE_ID) values(?,?,?,?)");
            //插入ss_hj_product_relation
            psHJProductRelation = con1.prepareStatement("insert into ss_hj_product_relation" +
                    "(PRODUCT_ID,AUTOID,RELATION_ID) values(?,?,?)");
            while (rs.next()) {
                    //聚合商品表
                    psHJProduct.setInt(1,productId);
                    psHJProduct.setInt(2,rs.getInt("classid"));
                    psHJProduct.setString(3,rs.getString("spname"));
                    psHJProduct.setString(4,rs.getString("sppic"));
                    psHJProduct.setInt(5,0);
                    psHJProduct.setInt(6,0);
                    psHJProduct.setInt(7,1);
                    psHJProduct.setInt(8,productId);
                    psHJProduct.setInt(9,rs.getInt("value_id"));
                    psHJProduct.addBatch();
                    //图片表
                    psHJProductPicture.setInt(1,productId);
                    psHJProductPicture.setString(2,rs.getString("sppic"));
                    psHJProductPicture.setString(3,rs.getString("sppic"));
                    psHJProductPicture.setInt(4,pictureId);
                    psHJProductPicture.addBatch();
                    //关系表
                    psHJProductRelation.setInt(1,productId);
                    psHJProductRelation.setInt(2,rs.getInt("id"));
                    psHJProductRelation.setInt(3,relationId);
                    psHJProductRelation.addBatch();
                    //id增加
                    productId++;
                    pictureId++;
                    relationId++;
                count++;
                if(count%100000==0) {//提交
                    psHJProduct.executeBatch();
                    psHJProductPicture.executeBatch();
                    psHJProductRelation.executeBatch();
                    con1.commit();
                }
            }
            //最后一批没有提交处理
            psHJProduct.executeBatch();
            psHJProductPicture.executeBatch();
            psHJProductRelation.executeBatch();
            con1.commit();
        } catch (Exception e) {
            logger.error("异常");
            e.printStackTrace();
        } finally {
            logger.error("=productId:"+productId);
            logger.error("=pictureId:"+pictureId);
            logger.error("=relationId:"+relationId);
            try {
                if(rs!=null){
                    rs.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if(psHJSearchResult!=null){
                    psHJSearchResult.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if(con!=null){
                    con.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return count;
    }

  3.2 JDBC批处理和ES Java Client批处理数据

四、总结

  1.JDBC要配置编码格式,不然可能出现乱码;

  2.因为数大数据量处理,编码时候注意JVM的GC回收;

  3.使用PreparedStatement处理数据;

原文地址:https://www.cnblogs.com/huangchanghuan/p/8034489.html