解决sqoop1.4.4无法导入oracle的blob字段到hbase的问题

来源:互联网 发布:zabbix监控nginx 编辑:程序博客网 时间:2024/05/18 03:40

最近在做oracle到hbase的数据迁移,有一张表有blob字段,在导入时发现没有导入成功,在网上找了好久,都没有搞定,最后没办法只能研究一下sqoop的源码,自己解决了。
在研究源码后,发现sqoop中已经有了关于blob字段的处理方法了,但不知道什么原因,对hbase没有正确处理,存在bug。主要做如下修改:

在org.apache.sqoop.mapreduce.HBaseImportMapper类中,增加大字段的处理。
 首先增加如下代码:
 这是在初始化时,初始化大对象读取器,构造函数中最后一个是null,如果单个文件大于设定的最大值(--inline-lob-limit属性,默认是16M),会报错,这块需要先写在hdfs上,也可以自己写一个hdfs的路径。
 private LargeObjectLoader lobLoader;
 protected void setup(Context context)
       throws IOException, InterruptedException {
    this.lobLoader = new LargeObjectLoader(context.getConfiguration(),
      null);
 
 }
 public void map(LongWritable key, SqoopRecord val, Context context)
 throws IOException, InterruptedException {
   /**原来的hbase map中是没有调用大对象的方法,在此处增加**/
   try {
       // Loading of LOBs was delayed until we have a Context.
       val.loadLargeObjects(lobLoader);
     } catch (SQLException sqlE) {
       throw new IOException(sqlE);
     }
  context.write(val, NullWritable.get());

}

增加完以后代码后,会发现导入到hbase的图片,比实际的大好多,我的大了一倍左右,且图片无法正常显示,这是因为sqoop在将程序入库时,字符转换有问题,可以做如下操作:

 在org.apache.sqoop.hbase.ToStringPutTransformer方法中,增加如下方法:
   /**
   * 如果是blob类型,转成string在转成byte后,结果会发生变化,有时候数据量会增大一倍,会出错。
   * @author sking modify 2014-12-25
   * @param val
   * @return
   */
  private byte[] toHBaseBytes(Object val) {
  
   if (val instanceof BlobRef){
    return ((BlobRef)val).getData();
   }else{
    return Bytes.toBytes(toHBaseString(val));
   }
  }
  并将  private List<Put> putRecordInHBase(Map<String, Object> record,String colFamily, String rowKey)方法中
      if (null != val) {
          put.add(colFamilyBytes, getFieldNameBytes(colName),
            Bytes.toBytes(toHBaseString(val)));
        }
改成
if (null != val) {
          put.add(colFamilyBytes, getFieldNameBytes(colName),
       

0 0
原创粉丝点击