背景说明:

最近做一个数据迁移的项目,遇到一个需求就是: 把关系型数据库的数据迁移到hdfs 上并且用hive表管理。本来是一个比较简单的需求,直接sqoop脚本 或者用阿里的datax。 但是要命的是,该需求要求可视化操作,也就是说,不能用跑脚本的形式。这个难不倒我,不就是调用api嘛,我再给你加一个web 就可以搞定,谁知道是噩梦的开始搞了一个星期终于搞定。先总结如下:
首先我们知道 sqoop 将数据导入hive 是分两步走
1 先自己生成一个map 之类的类,自己编译 ,将数据导入hdfs ,此时如果你指定存放零食表位置,那么就是在你指定的文件中,如果没有指定,则存放在user/你的用户名/抽取的表名下
2 第二步是分两步走的
2.1 先建表
2.2 load 数据到hive 表。


上边的都是屁话,大家都知道 ,关键是第二步,我是用的sqoop的api 甚是简单,第一步很容易成功
从网上抄来代码,直接复制粘贴,跑起来没问题。可是发现数据只到了hdfs 却没有到hive ,此时奇怪的时候程序没有报错。 并且最后给出的提示是 load data into hive sucess 之类的。
最后发现问题出现了环境配置上。
话分两头,先说代码跟踪
sqoop导入第一步 到hdfs 成功后,sqoop 会判断用户是否配置了导入hive 如果有的话,就会生成两个命令 一个是建表语句 一个是load data inpath “ path ” into hive表;并且以文件的形式保存在本地,(具体位置是idea所在pan 的根目录下一个temp文件夹中)
然后再调用hive安装包中的bin 目录下的 hive.cmd 文件 参数是 -f 执行语句文件
在hive.cmd 中调用 hive-config.cmd 设置hive_home 接着返回hive.cmd 在本脚本中最重要的一件事就是设置变量%HIVEARGS%(它的值就是-f 执行语句文件)
设置完毕后 ,通过调用 call %HIVE_BIN_PATH%\ext%TORUN%.cmd %TORUN% %*
上边的翻译一个就是调用本文件夹下的ext文件夹中的cli.cmd -f 执行语句文件
我们进入ext cli.cmd 中 它就做了两件事
1 设置CLASS(org.apache.hive.beeline.cli.HiveCli)2 调用call %HIVE_BIN_PATH%\ext\util\execHiveCmd.cmd %CLASS%
我们进入ext\util\execHiveCmd.cmd 中 它干了一件事
call %HADOOP% jar %JAR% %CLASS% %HIVE_OPTS% %HIVEARGS% 就是调用hadoop 中的bin
的hadoop.cmd
此时才开始真正的执行 导入操作。

总结:

上边写的很乱 也很烂 ,我在这里总结一下:
sqoop api 导入 hive(windows下开发的) 主要在第二步 (就是把文件从hdfs的临时存放位置load进hive ) 的过程是
执行java 调用执行cmd 命令 过程中用到的文件是
hive.cmd —>hive-config.cmd---->ext\cli.cmd---->\ext\util\execHiveCmd.cmd----->$HADOOP_HOME\bin\hadoop.cmd .
可以看到基本都是脚本的形式的跑的,所以过程中需要注意环境变量,因为环境变量设置错误,而脚本也报错,就会导致java jdk 以为脚本跑成功,返回给我们假的装在数据成功信息,就像我的一样。

用到的环境 是
1 JAVA_HOME 需要在环境变量中配置
2 HADOOP_HOME (参考windows 设置环境变量的操作)
3 HIVE_HOME (你想将数据导入到哪个集群,最简单的办法就是去该集群 将配置好的hive安装文件复制到本地,并且让HIVE_HOME指向该地址)
连接代码

import org.apache.hadoop.conf.Configuration;
import org.apache.sqoop.Sqoop;
import org.apache.sqoop.tool.SqoopTool;
import org.apache.sqoop.util.OptionsFileUtil;

/**
 * @author roman
 * @version 1.0
 * @description
 * @date 2021/3/26 14:17
 */

public class Demo {


    public int importDataFromOracle() {
        String[] args = new String[]{
                "--connect", "jdbc:oracle:thin:@192.168.10.12:1521:ftmsdev",
                "--username", "ftms",
                "--password", "ftms",
                "--table", "SYSTEM_USER",
                "--columns", "LOGIN_NAME,PASSWORD",
                "--split-by", "USER_ID",
                "--target-dir", "ftms/tables/system_user"
        };

        String[] expandedArgs = null;
        try {
            expandedArgs = OptionsFileUtil.expandArguments(args);
        } catch (Exception e) {
            System.err.println(e.getMessage());
            System.err.println("Try 'sqoop help' for usage.");
        }

        com.cloudera.sqoop.tool.SqoopTool tool = (com.cloudera.sqoop.tool.SqoopTool) SqoopTool.getTool("import");
        //com.cloudera.sqoop.tool.SqoopTool tool = new ImportTool();

        Configuration conf = new Configuration();
        conf.set("fs.default.name", "hdfs://192.168.242.128:9000");//设置hadoop服务地址
        Configuration pluginConf = null;// SqoolTool.loadPlugins(conf);

        Sqoop sqoop = new Sqoop(tool, pluginConf);
        return Sqoop.runSqoop(sqoop, expandedArgs);
    }

    private static int importData() throws Exception {
        String[] args = new String[]{
                "--connect", "jdbc:mysql://172.16.35.11:3306/datav_db \\",
                "--driver", "com.mysql.jdbc.Driver",
                "--username", "root",
                "--password", "root",
                "--table", "t_dept1",
                "--num-mappers", "1",
                "--hive-import",
                "--target-dir", "/user/company",
                "--hive-table", "yanshi.staff_hive",
                "--fields-terminated-by", "\t",
                "--create-hive-table"


        };
        String[] args1 = new String[]{
//                "--hive-home","/opt/cloudera/parcels/CDH/lib/hive",
//                "--hadoop-mapred-home","/opt/cloudera/parcels/CDH/lib/hadoop",
                "--connect", "jdbc:mysql://172.16.35.11:3306/datav_db",
                "--username", "root",
                "--password", "root",
                "--table", "dv_dataset",
                "--hive-import",
                "--hive-table", "yanshi.dv",
                "--fields-terminated-by", "\t",
                "--num-mappers", "1",
                "--target-dir", "/user/company",
                "--delete-target-dir"
/*
* --connect jdbc:mysql://172.16.35.11:3306/datav_db \
--username root \
--password root \
--table dv_analysis \
--num-mappers 1 \
--hive-import \
--fields-terminated-by "\t" \
--hive-overwrite \
--hive-table dv_analysis
*
* */

        };

        String[] expandArguments = OptionsFileUtil.expandArguments(args1);

        SqoopTool tool = SqoopTool.getTool("import");

        Configuration conf = new Configuration();
        // 设置hdfs 的namenode的通信地址 ,需要注意的是原生的hdfs端口是9000,此时我的是cdh版本的
        conf.set("fs.default.name", "hdfs://172.16.35.11:8020");
        conf.set("hive.metastore.uris", "thrift://172.16.35.11:9083");
        conf.set("hive.metastore.warehouse.dir", "/user/hive/warehouse");
        conf.set("hive.zookeeper.quorum", "172.16.35.12,172.16.35.13,172.16.35.14");
        conf.set("hive.zookeeper.client.port", "2181");
        conf.set("hive.vectorized.use.vector.serde.deserialize", "false");
        Configuration loadPlugins = SqoopTool.loadPlugins(conf);

        Sqoop sqoop = new Sqoop((com.cloudera.sqoop.tool.SqoopTool) tool, loadPlugins);
        System.out.println("开始执行文件");
        return Sqoop.runSqoop(sqoop, expandArguments);
    }

    public static void main(String[] args) {

        String curClasspath = System.getProperty("java.class.path");

        try {
            System.out.println("curClasspath==" + curClasspath);
            System.out.println("开始执行");
            importData();`在这里插入代码片`
            System.out.println("=================执行结束");
        } catch (Exception e) {

            e.printStackTrace();
        }
    }
}

maven 坐标

<properties>
        <hadoop.version>2.10.1</hadoop.version>
        <spark.version>2.1.1</spark.version>
        <scala.version>2.11.8</scala.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.apache.sqoop</groupId>
            <artifactId>sqoop</artifactId>
            <version>1.4.6</version>
        </dependency>

        <!-- hdfs依赖 -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>${hadoop.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>${hadoop.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>${hadoop.version}</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.37</version>
        </dependency>

注意这里的1.4.6 如果下载不下来,可以下载安装包 解压,根目录下有对应的jar包 然后自己制作一个本地的maven坐标搞定
制作maven本地坐标的命令
mvn install:install-file -DgroupId=org.apache.sqoop -DartifactId=sqoop -Dversion=1.4.6 Dpackaging=jar -Dfile=jar包路径(替换成你自己的)