设为首页 加入收藏

TOP

Hadoop实战学习(3)-读取数据库内容
2019-05-10 00:41:02 】 浏览:60
Tags:Hadoop 实战 学习 读取 数据库 内容

要读取数据库中的数据,首先需要实现一个实体类,这个实体类部分映射数据库中要查询的表的字段。且该实体类需要实

现Writable与DBWritable两个接口,DBWritable的实现类负责查询与写入,Writable的实现类负责序列化输出(到Mapper)与写入。

可以将两个接口的实现都写入到一个类。

开发环境:mysql-5.7,Hadoop-2.7.3集群,Idea(Linux版),ubuntu。

开发测试都是在Linux环境下执行的。

SQL语句及数据准备:

CREATE DATABASE BigData DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

use BigData;

CREATE TABLE author (
    id int primary key auto_increment not null ,    
    name varchar(20) null,
    sex  char(1) null,  
    remark varchar(255) null
) DEFAULT CHARSET=utf8;

insert into author(name,sex,remark) values ('李三','0','Hello 李三');
insert into author(name,sex,remark) values ('李芳','1','Hello 李芳');
insert into author(name,sex,remark) values ('张燕','1','Hello 张燕');
insert into author(name,sex,remark) values ('王5','0','Hello 王5');
insert into author(name,sex,remark) values ('李四','0','How are you 李四');
insert into author(name,sex,remark) values ('李7','0','Hello 李7');

代码:

Writable及DBWritable接口实现类。

package com.readdb;

import org.apache.hadoop.io.Writable;
import org.apache.hadoop.mapreduce.lib.db.DBWritable;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 该类在Mapper前执行
 */
public class MyDBWriteable implements DBWritable,Writable {

    private String name,sex,remark;

    private int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    /**     
     * 序列化输出对象字段,将查询结果作为mapper的输入
     * 即将查询结果写入到Mapper的输入数据
     * @param dataOutput
     * @throws IOException
     */
    public void write(DataOutput dataOutput) throws IOException {
        dataOutput.writeInt(id);
        dataOutput.writeUTF(sex);
        dataOutput.writeUTF(name);
        dataOutput.writeUTF(remark);
    }

    /**         
     * 读取向数据库写入输入字段,读取数据时可以不实现该方法
     * @param dataInput
     * @throws IOException
     */
    public void readFields(DataInput dataInput) throws IOException {
        //id=dataInput.readInt();
        //sex=dataInput.readUTF();
        //name=dataInput.readUTF();
        //remark=dataInput.readUTF();
    }

    /**     
     * 向数据库写入数据,只读数据的话该方法可以不写
     * @param statement
     * @throws SQLException
     */
    public void write(PreparedStatement statement) throws SQLException {
        //写入顺序要与列顺序一致
        //statement.setInt(1,id);
        //statement.setString(2,name);
        //statement.setString(3,sex);
        //statement.setString(4,remark);
    }

    /**     
     * 读取查询结果集
     * @param resultSet
     * @throws SQLException
     */

    public void readFields(ResultSet resultSet) throws SQLException {
        id=resultSet.getInt(1);
        name=resultSet.getString(2);
        sex=resultSet.getString(3);
        remark=resultSet.getString(4);
    }
}

Mapper:

package com.readdb;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;
import java.util.StringTokenizer;

public class WCMapper extends Mapper<LongWritable,MyDBWriteable,Text,IntWritable> {
    @Override
    protected void map(LongWritable key, MyDBWriteable value, Context context) throws IOException, InterruptedException {
        StringTokenizer stringTokenizer=new StringTokenizer(value.getRemark());
        while (stringTokenizer.hasMoreTokens()){
            context.write(new Text(stringTokenizer.nextToken()),new IntWritable(1));
        }
    }
}

Reducer:

package com.readdb;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

public class WCReducer extends Reducer<Text,IntWritable,Text,IntWritable> {

    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
        int count=0;
        for (IntWritable intWritable:values){
            count+=intWritable.get();
        }
        context.write(key,new IntWritable(count));
    }
}

作业执行:

package com.readdb;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.db.DBConfiguration;
import org.apache.hadoop.mapreduce.lib.db.DBInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;

import java.io.IOException;

public class HDFSDemo {

    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
        Configuration configuration=new Configuration();
        //配置作业
        Job job=Job.getInstance(configuration,"readdb");
        String[] otherArgs = new GenericOptionsParser(configuration, args).getRemainingArgs();
        if (otherArgs.length != 1) {
            System.err.println("Usage: wordcount <out>");
            System.exit(2);
        }else {
            FileSystem.get(configuration).delete(new Path(otherArgs[0]));
        }
        //配置数据库信息
        String driverClass="com.mysql.jdbc.Driver";
        String url="jdbc:mysql://127.0.0.1:3306/BigDatauseUnicode=true&characterEncoding=utf8&useSSL=false";
        String userName="root";
        String password="123456";
        String querySelect="select * from author";
        String queryCount="select count(*) from author";
        //配置数据库
        DBConfiguration.configureDB(job.getConfiguration(),driverClass,url,userName,password);
        //配置Mapper数据输入
        DBInputFormat.setInput(job,MyDBWriteable.class,querySelect,queryCount);
        //设置搜索类
        job.setJarByClass(HDFSDemo.class);
        //设置输入格式,TextInputFormat是默认输入格式,不能设置成FileInputFormat.Class,该惨数在当前情况下可以不设置
        job.setInputFormatClass(DBInputFormat.class);
        //设置Mapper类
        job.setMapperClass(WCMapper.class);
        //设置Reducer类
        job.setReducerClass(WCReducer.class);
        //设置Reducer个数
        //job.setNumReduceTasks(1);
        //设置maper端单词输出格式
        job.setMapOutputKeyClass(Text.class);
        //设置mapper端单词输出个数格式
        job.setMapOutputValueClass(IntWritable.class);
        //设置Reducer端单词输出格式
        job.setOutputKeyClass(Text.class);
        //设置Reducer单词输出个数格式
        job.setOutputValueClass(IntWritable.class);
        //设置job的输入路径,多次add可以设置多个输入路径
        //FileInputFormat.addInputPath(job,new Path(otherArgs[0]));
        //设置输出路径
        FileOutputFormat.setOutputPath(job,new Path(otherArgs[0]));
        System.exit(job.waitForCompletion(true)  0 : 1);
    }

}

然后点击Idea菜单栏的Run->Edit Configurations配置参数。

这里只需要配置输出目录。


然后编译运行。如果编译通过了,会在用户主目录下产生一个out目录。


然后执行命令:cat ~/out/* 查看输出结果。


可以看到,hadoop作业输出结果与mysql数据表中的数据完全符合。然后将代码打成jar包,在集群上运行。

打包之前,记得修改代码中的ip地址,我这里配置的是本机地址。改成内网ip后打包。


可以看到已经打成jar包了。然后将jar包移动到用户主目录下。


如果Idea所在的主机就是NameNode,当然也可以直接在IDea中执行jar包。

如果不是,还需要将jar包复制到NameNode上面。

允许jar包之前,还需要拷贝mysql的驱动(mysql-connector-java-5.1.38.jar)到各个节点的${HADOOP_HOME}/share/hadoop/common/lib目录下。也可以拷贝到${HADOOP_HOME}/share/hadoop/hdfs/lib目录下。

然后执行:hadoop jar readdb-core-1.0-SNAPSHOT.jar com.readdb.HDFSDemo /user/zhang/hadoop/out


然后查看输出结果:


可以看到输出结果和mysql表中的 数据一致。

常见问题解决:

1.提示驱动类找不到是因为没有加载mysql驱动jar包。

2.提示数据库找不到是因为ip地址配置错误,在执行jar包的时候,ip地址不能使用127.0.0.1;

3.无法连接到数据库,数据库访问被拒绝可以点此查看ubuntu无法访问mysql数据库

4.如果重复出现以下情况:


配置historyserver,执行:mr-jobhistory-daemon.sh start historyserver即可解决。

点此下载源代码

源代码下载完成后,先执行SQL语句,然后以导入maven工程的方式导入root目录下的pom.xml,只需要导入这一关pom.xml即可。


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇结合案例讲解MapReduce重要知识点.. 下一篇2018-3-7      ..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目