还是一样,要先引入依赖,在pom.xml
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-planner_2.12</artifactId>
<version>1.10.1</version>
</dependency>
从文件中读取数据
新建一个 TableApiFromFile的object:
/**
*
* @author mafei
* @date 2020/11/22
*
* 把txt内容注册成为表,按照预期的格式输出出来
*/
package com.mafei.apitest.tabletest
import org.apache.flink.streaming.api.scala._
import org.apache.flink.table.api.{DataTypes, Table}
import org.apache.flink.table.api.scala._
import org.apache.flink.table.descriptors.{Csv, FileSystem, OldCsv, Schema}
object TableApiFromFile {
def main(args: Array[String]): Unit = {
//1 、创建环境
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.setParallelism(1)
val tableEnv = StreamTableEnvironment.create(env)
//2、读取文件
val filePath = "/opt/java2020_study/maven/flink1/src/main/resources/sensor.txt"
tableEnv.connect(new FileSystem().path(filePath))
.withFormat(new Csv()) //因为txt里头是以,分割的跟csv一样,所以可以用oldCsv
.withSchema(new Schema() //这个表结构要跟你txt中的内容对的上
.field("id", DataTypes.STRING())
.field("timestamp", DataTypes.BIGINT())
.field("temperature", DataTypes.DOUBLE())
).createTemporaryTable("inputTable")
val inputTable: Table = tableEnv.from("inputTable") //就是上面创建的表名
inputTable.toAppendStream[(String, Long, Double)].print()
tableEnv.execute("table api test from file")
}
}
############ 上面的OldCsv已经废弃,如果要用新的方法,需要单独引入一个依赖在pom.xml中添加 #######################
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-csv</artifactId>
<version>1.10.1</version>
</dependency>
对应代码使用只需要把OldCsv方法改成Csv就可以了
.withFormat(new Csv())
代码结构及运行效果:
从kafka中读取数据
关于kafka的基础知识和安装可以参考: https://blog.51cto.com/mapengfei/1926065
/**
*
* @author mafei
* @date 2020/11/22
*/
package com.mafei.apitest.tabletest
import org.apache.flink.streaming.api.scala._
import org.apache.flink.table.api.{DataTypes, Table}
import org.apache.flink.table.api.scala._
import org.apache.flink.table.descriptors.{Csv, Kafka, Schema}
object TableApiFromKafka {
def main(args: Array[String]): Unit = {
//1 、创建环境
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.setParallelism(1)
val tableEnv = StreamTableEnvironment.create(env)
//2、从kafka中读取数据
tableEnv.connect(
new Kafka()
.version("0.11")
.topic("sensor1")
.startFromLatest()
.property("zookeeper.connect", "localhost:2181")
.property("bootstrap.servers", "localhost:9092")
).withFormat(new Csv())
.withSchema(new Schema() //这个表结构要跟你kafka中的内容对的上
.field("id", DataTypes.STRING())
.field("timestamp", DataTypes.BIGINT())
.field("temperature", DataTypes.DOUBLE())
)
/**
* 如果是json也是一样,需要引入单独的flink-json
* <dependency>
* <groupId>org.apache.flink</groupId>
* <artifactId>flink-json</artifactId>
* <version>1.10.1</version>
* </dependency>
*/
.createTemporaryTable("kafkaInputTable")
val inputTable: Table = tableEnv.from("kafkaInputTable")
inputTable.toAppendStream[(String,Long,Double)].print()
env.execute("table api test from kafka! ")
}
}
启动kafka服务,并开一个producer命令行,写入几条数据进去(注意是要符合预期的格式)
/opt/kafka_2.11-0.10.2.0/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic sensor1
各种转换操作
目标: 从文件中读取数据,分别使用table api 和SQL这2种方式来实现过滤转换格式等操作
/**
*
* @author mafei
* @date 2020/11/22
*/
package com.mafei.apitest.tabletest
import org.apache.flink.streaming.api.scala._
import org.apache.flink.table.api.{DataTypes, Table}
import org.apache.flink.table.api.scala._
import org.apache.flink.table.descriptors.{Csv, FileSystem, Schema}
object TableApiTransform {
def main(args: Array[String]): Unit = {
//1 、创建环境
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.setParallelism(1)
val tableEnv = StreamTableEnvironment.create(env)
//2、读取文件
val filePath = "/opt/java2020_study/maven/flink1/src/main/resources/sensor.txt"
tableEnv.connect(new FileSystem().path(filePath))
.withFormat(new Csv()) //因为txt里头是以,分割的跟csv一样,所以可以用oldCsv
.withSchema(new Schema() //这个表结构要跟你txt中的内容对的上
.field("id", DataTypes.STRING())
.field("timestamp", DataTypes.BIGINT())
.field("temperature", DataTypes.DOUBLE())
).createTemporaryTable("inputTable")
val inputTable: Table = tableEnv.from("inputTable") //就是上面创建的表名
//3、查询转换
//第一种,使用table api
val sensorTable = tableEnv.from("inputTable")
val resultTable = sensorTable
//可以用scala里面的表达式来写
.select('id,'temperature)
.filter('id === "sensor1")
//也可以这样子常规的写法
// .select("id,temperature")
// .filter("`id`='sensor1'")
//第二种,使用SQL来实现
val resultSqlTable = tableEnv.sqlQuery(
"""
|select id, temperature
|from inputTable
|where id='sensor1'
|""".stripMargin
)
resultTable.toAppendStream[(String, Double)].print("table result:")
resultSqlTable.toAppendStream[(String,Double)].print("sql result: ")
inputTable.toAppendStream[(String, Long, Double)].print("原始的,没做任何处理:")
tableEnv.execute("table api test from file")
}
}
代码结构及运行效果
将DataStream转换成表
对于一个DataStream,可以直接转换成Table,进而方便的调用Table API做转换操作
val dataStream: DataStream[SensorReadingTest5] = ....
val sensorTable: Table = tableEnv.fromDataStream(dataStream)
默认转换后的Table scheam和DataStream中的字段定义一一对应,也可以单独指定出来
val dataStream: DataStream[SensorReadingTest5] = ...
val sensorTable = tableEnv.fromDataStream(dataStream,'id,'timestamp,'temperature)
数据类型与Schema的对应
DataStream中的数据类型,与表的Scheam之间的对应关系,可以有两种: 基于字段名称,或者字段的位置
基于名称(name-based)
val sensorTable = tableEnv.fromDataStream(dataStream,'timestamp as 'ts, 'id as 'myId, 'temperature)
基于位置(position-based)
val sensorTable = tableEnv.fromDataStream(dataStream,'myId,'ts)
创建临时视图(Temporary View)
tableEnv.createTemporaryView("sensorView", dataStream)
tableEnv.createTemporaryView("sensorView",dataStream,'id, 'temperature, 'timestamp as 'ts)
基于Table创建临时视图
tableEnv.createTemporaryView("sensorView", sensorTable)
输出表
表的输出是通过将数据写入TableSink来实现的
TableSink是一个通用接口,可以支持不同的文件格式、存储数据库和消息队列
输出表最直接的方法就是通过Table.insertinto()方法将一个Table写入注册过的TableSink中
tableEnv.connect(....).createTemporaryTable("outputTable")
val resultSqlTable: Table = .... resultTable.insertInto("outputTable")