首页 > 代码库 > hive 采用JDBC编码方式获取外部分区表数据

hive 采用JDBC编码方式获取外部分区表数据

    由于最近项目的需求,仔细研究了下采用hive JDBC编码的方式来实现命令行模式执行hql语句的功能。期间遇到了不少问题,并一一进行了分析解决。但是时间匆忙,本人并未能将遇到的问题逐一记录在案。凭借零零稀稀的记忆希望将这些问题和经验进行总结以备后用。

    项目中有个需求就是实现通过hql条件查询语句查询出hive外部分区表中的数据,并将这些数据保存到本地文件中。直接贴出查询的主要类似代码如下:

    String driverName = "org.apache.hadoop.hive.jdbc.HiveDriver";
    try {
      Class.forName(driverName);
    } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      System.exit(1);
     }
     Connection con = DriverManager.getConnection("jdbc:hive://localhost:10000/default", "", "");
     Statement stmt = con.createStatement();
     ResultSet rs=stmt.executeQuery("select * from mytable limit 10"); 
     while(rs.next()){
        System.out.println(rs.getString(0));//第一列为String类型数据
     }

    但是在运行代码时会出现异常,提示如下:

    java.sql.SQLException: java.lang.ArrayIndexOutOfBoundsException: -1

    报的错为数组越界异常(奇怪!以前在普通hive表中采用这种方式获取列值时没出现这种异常。),百思不得其解。尝试使用ResultSet的其他靠谱点的get方法获取第一列的值,依旧报数组越界错或者方法不支持错,看来hive的jdbc方式并未实现所有的ResultSet方法。

    最后将出现异常的那行做了下修改,采用rs的getString方法调用列名参数,结果成功了。修改后的代码如下所示:

      String driverName = "org.apache.hadoop.hive.jdbc.HiveDriver";
      try {
       Class.forName(driverName);
      } catch (ClassNotFoundException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
        System.exit(1);
      }
     Connection con = DriverManager.getConnection("jdbc:hive://localhost:10000/default", "", "");
     Statement stmt = con.createStatement();
     ResultSet rs=stmt.executeQuery("select * from mytable limit 10");
     ResultSetMetaData rsmd = rs.getMetaData();
     int count=rsmd.getColumnCount();
     String[] name=new String[count];
     for(int i=0;i<count;i++)
       name[i]=rsmd.getColumnName(i+1);
     while(rs.next()){
      //System.out.println(rs.getString(0));
      for(int i=0;i<count;i++)
       System.out.print(rs.getString(name[i])+",");
      System.out.println();
     }

    总结:在hive 的JDBC编码方式实现hql语句功能中,ResultSet的get+类型方法可能并不总能支持传递索引参数,这时我们得考虑换种思路,采用传递列名的方式获取值。