SparkSql 02 dataset表创建

写sql之前需要先创建SparkSession对象
基本格式:

// SparkSession对象
SparkSession sparkSession = SparkSession.builder()
        .appName("sql")
        .master("local")
        .getOrCreate();

创建Dataset(表)两种方式

代码示例:

package com.shsxt.spark.java;

import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.SparkSession;

/**
 * Created by BF-Lone Silver Wind
 */
public class SqlTest {
    public static void main(String[] args) {
        // SparkSession对象
        SparkSession sparkSession = SparkSession.builder()
                .appName("sql")
                .master("local")
                .getOrCreate();
        //根据数据创建表
        //Dataset<Row> dataset = sparkSession.read().json("json");
        Dataset<Row> dataset = sparkSession.read().format("json").load("json");

        //打印 元数据
        dataset.printSchema();

        //打印表
        //默认按表字段的ascii 来排序
        dataset.show();
        
        //Spark自带api操作 不推荐使用
        //Dataset<Row> dataset1 = dataset.select("name", "age").where("age>18");
        //Dataset<Row> dataset1 = dataset.select(dataset.col( "name"),dataset.col( "age").plus(10)).where("age>18");

        //dataset1.show();
        
        //先创建临时表
        dataset.registerTempTable("jsonTable");
        //SparkSession对象调用sql方法直接输入sql查询
        Dataset<Row> rowDataset = sparkSession.sql("select name,age,age + 10  from jsonTable where age > 18");

        rowDataset.show();
    }
}

注意:

  • 1.读取json格式两种方式
  • 2.ds.show默认显示前20行,使用ds.show(行数)显示多行
  • 3.ds.javaRDD/(scala ds.rdd) 将DataFrame转换成RDD
  • 4.ds.printSchema()显示Dataset中的Schema信息
  • 5.dataset自带的API 操作Dataset ,用的少
  • 6.想使用sql查询,首先要将Dataset注册成临时表:dd.registerTempTable(“jtable”),再使用sql,怎么使用sql? sparksession.sql(“sql语句”)
  • 7.不能读取嵌套的json文件
  • 8.ds加载过来之后将列按照ascii排序了
1. 通过已知json文件创建dataset表:

方式一:

//已知json格式文件读取"json"文件创建dataset
Dataset<Row> dataset = sparkSession.read().json("json");

方式二:

//填写文件格式并读取"json"文件创建dataset
Dataset<Row> dataset = sparkSession.read().format("json").load("json");
2. 通过json格式的RDD创建Dataset
//通过SparkSession对象创建SparkContext上下文对象
SparkContext sc = sparkSession.sparkContext();
//通过SparkContext上下文对象new一个JavaSparkContext对象
JavaSparkContext jsc = new JavaSparkContext(sc);

//json 1
JavaRDD<String> nameRDD = jsc.parallelize(Arrays.asList(
		"{'name':'zhangsan','age':\"18\"}",
		"{\"name\":\"lisi\",\"age\":\"19\"}",
		"{\"name\":\"wangwu\",\"age\":\"20\"}"
		));
//json 2
JavaRDD<String> scoreRDD = jsc.parallelize(Arrays.asList(
		"{\"name\":\"zhangsan\",\"score\":\"100\"}",
		"{\"name\":\"lisi\",\"score\":\"200\"}",
		"{\"name\":\"wangwu\",\"score\":\"300\"}"
		));

//Dataset表name
Dataset<Row> nameds = sparkSession.read().json(nameRDD);
//Dataset表score
Dataset<Row> scoreds = sparkSession.read().json(scoreRDD);
3. 非json格式的RDD创建Dataset
1). 通过反射的方式将非json格式的RDD转换成Dataset
  • 自定义类要可序列化
  • 自定义类的访问级别是Public
  • RDD转成Dataset后会根据映射将字段按Assci码排序
  • 将Dataset转换成RDD时获取字段两种方式,一种是ds.getInt(0)下标获取(不推荐使用 存储 修改值任意出错),另一种是ds.getAs(“列名”)获取(推荐使用)
/**
* 注意:
* 1.自定义类必须是可序列化的
* 2.自定义类访问级别必须是Public
* 3.RDD转成Dataset会把自定义类中字段的名称按assci码排序
*/
SparkSession sparkSession = SparkSession
        .builder()
        .appName("reflect")
        .master("local")
        .getOrCreate();

SparkContext sc = sparkSession.sparkContext();

JavaSparkContext jsc = new JavaSparkContext(sc);

JavaRDD<String> lineRDD = jsc.textFile("person.txt");

JavaRDD<Person> personRDD = lineRDD.map(
        new Function<String, Person>() {

    private static final long serialVersionUID = 1L;

    @Override
    public Person call(String line) throws Exception {
        Person p = new Person();

        p.setId(line.split(",")[0]);
        p.setName(line.split(",")[1]);
        p.setAge(Integer.valueOf(line.split(",")[2]));
        return p;
    }
});
/**
* 传入进去Person.class的时候,sqlContext是通过反射的方式创建DataFrame
* 在底层通过反射的方式获得Person的所有field,结合RDD本身,就生成了DataFrame
*/
Dataset<Row> dataFrame = sparkSession.createDataFrame(personRDD, Person.class);
        dataFrame.show();
        dataFrame.printSchema();
        dataFrame.registerTempTable("person");
Dataset sql = sparkSession.sql("select  name,id,age from person where id = 2");
        sql.show();
        
/**
* 将Dataset转成JavaRDD
* 注意:
* 1.可以使用row.getInt(0),row.getString(1)...通过下标获取返回Row类型的数据,但是要注意列顺序问题---不常用
* 2.可以使用row.getAs("列名")来获取对应的列值。
* 
*/
JavaRDD<Row> javaRDD = df.javaRDD();
JavaRDD<Person> map = javaRDD.map(new Function<Row, Person>() {

	/**
	* 
	*/
	private static final long serialVersionUID = 1L;

	@Override
	public Person call(Row row) throws Exception {
            Person p = new Person();
            //p.setId(row.getString(1));
            //p.setName(row.getString(2));
            //p.setAge(row.getInt(0));

            p.setId((String)row.getAs("id"));
            p.setName((String)row.getAs("name"));
            p.setAge((Integer)row.getAs("age"));
            return p;
	}
});
map.foreach(x-> System.out.println(x));

sc.stop();

2). 动态创建Schema将非json格式的RDD转换成Dataset
/**
 * 动态构建DataFrame中的元数据,一般来说这里的字段可以来源自字符串,也可以来源于外部数据库
 */
List<StructField> asList =Arrays.asList(
	DataTypes.createStructField("id", DataTypes.StringType, true),
	DataTypes.createStructField("name", DataTypes.StringType, true),
	DataTypes.createStructField("age", DataTypes.IntegerType, true)
);

StructType schema = DataTypes.createStructType(asList);
Dataset<Row> df = sparkSession.createDataFrame(rowRDD, schema);
df.show();
sc.stop();

4. 读取parquet文件创建Dataset
  • 可以将Dataset存储成parquet文件。保存成parquet文件的方式有两种
//方式1
ds.write().mode(SaveMode.Overwrite)format("parquet").save("parquet_table");

//方式2
ds.write().mode(SaveMode.Overwrite).parquet("parquet_table");

  • SaveMode指定文件保存时的模式。
    Overwrite:覆盖
    Append:追加
    ErrorIfExists:如果存在就报错
    Ignore:如果存在就忽略
5. 读取JDBC中的数据创建Dataset(MySql为例)
SparkSession sparkSession = SparkSession
                .builder()
                .appName("mysql")
                .master("local")
                .getOrCreate();/**
 * 第一种方式读取MySql数据库表,加载为DataFrame
 */
Map<String, String> options = new HashMap<String,String>();
options.put("url", "jdbc:mysql://192.168.179.4:3306/spark");
options.put("driver", "com.mysql.jdbc.Driver");
options.put("user", "root");
options.put("password", "123456");
options.put("dbtable", "person");
Dataset<Row> person = sparkSession.read().format("jdbc").options(options).load(); 
person.show();
person.createOrReplaceTempView("person"); 
/**
 * 第二种方式读取MySql数据表加载为Dataset
 */
DataFrameReader reader = sparkSession.read().format("jdbc");
reader.option("url", "jdbc:mysql://192.168.179.4:3306/spark");
reader.option("driver", "com.mysql.jdbc.Driver");
reader.option("user", "root");
reader.option("password", "123456");
reader.option("dbtable", "score");
Dataset<Row> score = reader.load();
score.show();
score.createOrReplaceTempView("score"); 

Dataset result = 
sparksession.sql("select person.id,person.name,score.score from person,score where person.name = score.name");
result.show();
/**
 * 将Dataset结果保存到Mysql中
 */
Properties properties = new Properties();
properties.setProperty("user", "root");
properties.setProperty("password", "root");
result.write().mode(SaveMode.Overwrite).jdbc("jdbc:mysql://192.168.179.4:3306/spark", "result", properties);

sc.stop();

6. 读取Hive中的数据加载成Dataset
SparkSession sparkSession = SparkSession
                .builder()
                .master("local")
                .appName("hvie")
                //开启hive的支持,接下来就可以操作hive表了
                // 前提需要是需要开启hive metastore 服务
                .enableHiveSupport()
                .getOrCreate();

   sparkSession.sql("USE spark");
   sparkSession.sql("DROP TABLE IF EXISTS student_infos");
//在hive中创建student_infos表
   sparkSession.sql("CREATE TABLE IF NOT EXISTS student_infos (name STRING,age INT) row format delimited fields terminated by '\t' ");
        sparkSession.sql("load data local inpath '/root/student_infos' into table student_infos");
        //注意:此种方式,程序需要能读取到数据(如/root/student_infos),同时也要能读取到 metastore服务的配置信息。

sparkSession.sql("DROP TABLE IF EXISTS student_scores");
sparkSession.sql("CREATE TABLE IF NOT EXISTS student_scores (name STRING, score INT) row format delimited fields terminated by '\t'");
        sparkSession.sql("LOAD DATA "
				+ "LOCAL INPATH '/root/student_scores'"
				+ "INTO TABLE student_scores");



//		Dataset<Row> df = hiveContext.table("student_infos");//读取Hive表加载Dataset方式
        /**
         * 查询表生成Dataset
         */
		Dataset<Row> goodStudentsDF = sparkSession.sql("SELECT si.name, si.age, ss.score "
				+ "FROM student_infos si "
				+ "JOIN student_scores ss "
				+ "ON si.name=ss.name "
				+ "WHERE ss.score>=80");

		goodStudentsDF.registerTempTable("goodstudent");
        Dataset<Row>  result = sparkSession.sql("select * from goodstudent");
		result.show();
		
		/**
		 * 将结果保存到hive表 good_student_infos
		 */
    sparkSession.sql("DROP TABLE IF EXISTS good_student_infos");
goodStudentsDF.write().mode(SaveMode.Overwrite).saveAsTable("good_student_infos");

    sparkSession.stop();


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值