__declspec(dllexport) lib中未导出_深入理解Sqoop的导入与导出—文末赠书

Sqoop在导入导出数据时都会使用代码生成器来创建对应表的实体类,用于保存从表中抽取的记录,默认存放于“/tmp/sqoop-root/compile/随机字符/”目录下,用户必须手动将此目录下的实体类jar包上传至Sqoop的lib目录下,才可执行导入导出操作。研究Sqoop生成的实体类有助于我们深入理解Sqoop。

例如,之前用到的temp类生成的源码如下:

// ORM class for table 'temp'

// WARNING: This class is AUTO-GENERATED. Modify at your own risk.

//

// Debug information:

// Generated date: Sun Dec 16 05:30:10 PST 2018

// For connector: org.apache.sqoop.manager.MySQLManager

import org.apache.hadoop.io.BytesWritable;

import org.apache.hadoop.io.Text;

import org.apache.hadoop.io.Writable;

import org.apache.hadoop.mapred.lib.db.DBWritable;

import com.cloudera.sqoop.lib.JdbcWritableBridge;

import com.cloudera.sqoop.lib.DelimiterSet;

import com.cloudera.sqoop.lib.FieldFormatter;

import com.cloudera.sqoop.lib.RecordParser;

import com.cloudera.sqoop.lib.BooleanParser;

import com.cloudera.sqoop.lib.BlobRef;

import com.cloudera.sqoop.lib.ClobRef;

import com.cloudera.sqoop.lib.LargeObjectLoader;

import com.cloudera.sqoop.lib.SqoopRecord;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.io.DataInput;

import java.io.DataOutput;

import java.io.IOException;

import java.nio.ByteBuffer;

import java.nio.CharBuffer;

import java.sql.Date;

import java.sql.Time;

import java.sql.Timestamp;

import java.util.Arrays;

import java.util.Iterator;

import java.util.List;

import java.util.Map;

import java.util.TreeMap;

public class temp extends SqoopRecord implements DBWritable, Writable {

private final int PROTOCOL_VERSION = 3;

public int getClassFormatVersion() { return PROTOCOL_VERSION; }

protected ResultSet __cur_result_set;

private String year;

public String get_year() {

return year;

}

public void set_year(String year) {

this.year = year;

}

public temp with_year(String year) {

this.year = year;

return this;

}

private Integer temperature;

public Integer get_temperature() {

return temperature;

}

public void set_temperature(Integer temperature) {

this.temperature = temperature;

}

public temp with_temperature(Integer temperature) {

this.temperature = temperature;

return this;

}

private Integer quality;

public Integer get_quality() {

return quality;

}

public void set_quality(Integer quality) {

this.quality = quality;

}

public temp with_quality(Integer quality) {

this.quality = quality;

return this;

}

public boolean equals(Object o) {

if (this == o) {

return true;

}

if (!(o instanceof temp)) {

return false;

}

temp that = (temp) o;

boolean equal = true;

equal = equal && (this.year == null ? that.year == null : this.year.equals(that.year));

equal = equal && (this.temperature == null ? that.temperature == null : this.temperature.equals(that.temperature));

equal = equal && (this.quality == null ? that.quality == null : this.quality.equals(that.quality));

return equal;

}

public void readFields(ResultSet __dbResults) throws SQLException {

this.__cur_result_set = __dbResults;

this.year = JdbcWritableBridge.readString(1, __dbResults);

this.temperature = JdbcWritableBridge.readInteger(2, __dbResults);

this.quality = JdbcWritableBridge.readInteger(3, __dbResults);

}

public void loadLargeObjects(LargeObjectLoader __loader)

throws SQLException, IOException, InterruptedException {

}

public void write(PreparedStatement __dbStmt) throws SQLException {

write(__dbStmt, 0);

}

public int write(PreparedStatement __dbStmt, int __off) throws SQLException {

JdbcWritableBridge.writeString(year, 1 + __off, 12, __dbStmt);

JdbcWritableBridge.writeInteger(temperature, 2 + __off, 4, __dbStmt);

JdbcWritableBridge.writeInteger(quality, 3 + __off, 4, __dbStmt);

return 3;

}

public void readFields(DataInput __dataIn) throws IOException {

if (__dataIn.readBoolean()) {

this.year = null;

} else {

this.year = Text.readString(__dataIn);

}

if (__dataIn.readBoolean()) {

this.temperature = null;

} else {

this.temperature = Integer.valueOf(__dataIn.readInt());

}

if (__dataIn.readBoolean()) {

this.quality = null;

} else {

this.quality = Integer.valueOf(__dataIn.readInt());

}

}

public void write(DataOutput __dataOut) throws IOException {

if (null == this.year) {

__dataOut.writeBoolean(true);

} else {

__dataOut.writeBoolean(false);

Text.writeString(__dataOut, year);

}

if (null == this.temperature) {

__dataOut.writeBoolean(true);

} else {

__dataOut.writeBoolean(false);

__dataOut.writeInt(this.temperature);

}

if (null == this.quality) {

__dataOut.writeBoolean(true);

} else {

__dataOut.writeBoolean(false);

__dataOut.writeInt(this.quality);

}

}

private final DelimiterSet __outputDelimiters = new DelimiterSet((char) 9, (char) 10, (char) 0, (char) 0, false);

public String toString() {

return toString(__outputDelimiters, true);

}

public String toString(DelimiterSet delimiters) {

return toString(delimiters, true);

}

public String toString(boolean useRecordDelim) {

return toString(__outputDelimiters, useRecordDelim);

}

public String toString(DelimiterSet delimiters, boolean useRecordDelim) {

StringBuilder __sb = new StringBuilder();

char fieldDelim = delimiters.getFieldsTerminatedBy();

__sb.append(FieldFormatter.escapeAndEnclose(year==null?"null":year, delimiters));

__sb.append(fieldDelim);

__sb.append(FieldFormatter.escapeAndEnclose(temperature==null?"null":"" + temperature, delimiters));

__sb.append(fieldDelim);

__sb.append(FieldFormatter.escapeAndEnclose(quality==null?"null":"" + quality, delimiters));

if (useRecordDelim) {

__sb.append(delimiters.getLinesTerminatedBy());

}

return __sb.toString();

}

private final DelimiterSet __inputDelimiters = new DelimiterSet((char) 9, (char) 10, (char) 0, (char) 0, false);

private RecordParser __parser;

public void parse(Text __record) throws RecordParser.ParseError {

if (null == this.__parser) {

this.__parser = new RecordParser(__inputDelimiters);

}

List __fields = this.__parser.parseRecord(__record);

__loadFromFields(__fields);

}

public void parse(CharSequence __record) throws RecordParser.ParseError {

if (null == this.__parser) {

this.__parser = new RecordParser(__inputDelimiters);

}

List __fields = this.__parser.parseRecord(__record);

__loadFromFields(__fields);

}

public void parse(byte [] __record) throws RecordParser.ParseError {

if (null == this.__parser) {

this.__parser = new RecordParser(__inputDelimiters);

}

List __fields = this.__parser.parseRecord(__record);

__loadFromFields(__fields);

}

public void parse(char [] __record) throws RecordParser.ParseError {

if (null == this.__parser) {

this.__parser = new RecordParser(__inputDelimiters);

}

List __fields = this.__parser.parseRecord(__record);

__loadFromFields(__fields);

}

public void parse(ByteBuffer __record) throws RecordParser.ParseError {

if (null == this.__parser) {

this.__parser = new RecordParser(__inputDelimiters);

}

List __fields = this.__parser.parseRecord(__record);

__loadFromFields(__fields);

}

public void parse(CharBuffer __record) throws RecordParser.ParseError {

if (null == this.__parser) {

this.__parser = new RecordParser(__inputDelimiters);

}

List __fields = this.__parser.parseRecord(__record);

__loadFromFields(__fields);

}

private void __loadFromFields(List fields) {

Iterator __it = fields.listIterator();

String __cur_str;

__cur_str = __it.next();

if (__cur_str.equals("null")) { this.year = null; } else {

this.year = __cur_str;

}

__cur_str = __it.next();

if (__cur_str.equals("null") || __cur_str.length() == 0) { this.temperature = null; } else {

this.temperature = Integer.valueOf(__cur_str);

}

__cur_str = __it.next();

if (__cur_str.equals("null") || __cur_str.length() == 0) { this.quality = null; } else {

this.quality = Integer.valueOf(__cur_str);

}

}

public Object clone() throws CloneNotSupportedException {

temp o = (temp) super.clone();

return o;

}

public Map getFieldMap() {

Map __sqoop$field_map = new TreeMap();

__sqoop$field_map.put("year", this.year);

__sqoop$field_map.put("temperature", this.temperature);

__sqoop$field_map.put("quality", this.quality);

return __sqoop$field_map;

}

public void setField(String __fieldName, Object __fieldVal) {

if ("year".equals(__fieldName)) {

this.year = (String) __fieldVal;

}

else if ("temperature".equals(__fieldName)) {

this.temperature = (Integer) __fieldVal;

}

else if ("quality".equals(__fieldName)) {

this.quality = (Integer) __fieldVal;

}

else {

throw new RuntimeException("No such field: " + __fieldName);

}

}

}

由源码可见,生成的实体类实现了DBWritable接口的序列化方法,,如图1所示,这些方法能使temp类和JDBC进行交互:

0e70124f76c26313ac8ccb28fc6654fd.png

图1 DBWritable接口方法

JDBC的Resultset接口提供了一个用于从查询结果中检索记录的游标,这里的readFields()方法将用ResultSet中一行数据的列来填充temp对象的字段。write()方法允许Sqoop将新的temp行插入表,这个过程称为“导出”。

Sqoop启动的MapReduce作业用到一个InputFormat,它可以通过JDBC从一个数据库表中读取部分内容。Hadoop提供的DataDBInputFormat能够为几个Map任务对查询结果进行划分。但是,为了获得更好的导入性能,经常将这样的查询划分到多个节点上执行。查询是根据一个“划分列”来进行划分的。根据表的元数据,Sqoop会选择一个合适的列作为划分列(通常是表的主键)。主键列中的最小值和最大值会被读出,与目标任务数一起用来确定每个Map任务要执行的查询。

例如,假设表中有100,000条记录,其id列的值为0-99,999。

在导入这张表时,Sqoop会判断出id是表的主键列。启动MapReduce作业时,用来执行导入的DataDrivenDBInputFormat便会发出一条类似于SELECT MIN(id),MAX(id) FROM table的查询语句。检索出的数据将用于对整个数据集进行划分。

假设指定并行运行5个Map任务(使用-m 5),这样便可以确定每个Map任务要执行的查询数据条件。划分列的选择是影响并行执行效率的重要因素。如果id列的值不是均匀分布的(也许在id值50,000到75,000的范围内没有记录),那么有一部分Map任务可能只有很少或没有工作要做,而其他任务则有很多工作要做。

在运行一个导入作业时,用户可以指定一个列作为划分列,从而调整作业的划分使其符合数据的真实分布。如果使用-m 1参数来让一个任务执行导入作业,就不再需要这个划分过程。

在生成反序列化代码和配置InputFormat之后,Sqoop将作业发送到MapReduce集群。Map任务执行查询并且将ResultSet中的数据反序列化到生成类的实例,这些数据要么被直接保存在SequenceFile文件中,要么在写到HDFS之前被转换成分隔的文本。

为了使用导入记录的个别字段,必须对字段分隔符(以及转义/包围字符)进行解析,抽出字段的值并转换为相应的数据类型。例如,在文本文件中,气候质量被表示成字符串“1",但必须被解析为Java的Integer或int类型的变量。Sqoop生成的实体类能够自动完成这个过程,使开发人员可以将精力集中在真正要运行的MapReduce作业上。每个自动生成的类都有几个名为parse()的重载方法,这些方法可以对表示为Text、Charsequence、char[]或其他常见类型的数据进行操作。

本文摘编自《大数据Hadoop 3.X分布式处理实战》,经出版方授权发布。

e8eccf08341f4c79da49c71a94d2a9b2.png

编辑推荐:

1.版本新。本书采用Hadoop3,版本较新,帮助读者学习前沿技术。

2.项目大。深度剖析日志分析、推荐系统、垃圾消息三大企业级项目实战案例。读者稍加改造,即可在生产环境中使用。

3.内容全。详细介绍HDFS、MapReduce、HBase、Hive、Sqoop、Spark 等主流大数据工具。

4.资源多。赠送12小时视频讲解和全书配套范例源码。

留言说出与hadoop相关的话题,精选留言一名评论送出此书。机会多多,不可错过!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值