Spark操作外部数据源之Mysql数据源

将RDD中数据写入到Mysql中

实际开发中常常将分析结果RDD保存至MySQL表中,使用foreachPartition函数;此外Spark中提供JdbcRDD用于从MySQL表中读取数据。

调用RDD#foreachPartition函数将每个分区数据保存至MySQL表中,保存时考虑降低RDD分区数目和批量插入,提升程序性能。

范例演示:将词频统计WordCount结果保存MySQL表tb_wordcount。

建表

USE db_test ;
CREATE TABLE `tb_wordcount` (
`count` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`word` varchar(100) NOT NULL,
PRIMARY KEY (`word`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ;

代码

import java.sql.{Connection, DriverManager, PreparedStatement}
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

object Write {
  def main(args: Array[String]): Unit = {
      println("哈哈1")
      // TODO 1.创建sc环境
      val sparkConf: SparkConf = new SparkConf()
        .setAppName(this.getClass.getSimpleName.stripSuffix("$"))
        .setMaster("local[2]")
      val sc: SparkContext = new SparkContext(sparkConf)
      // 1. 从HDFS读取文本数据,封装集合RDD
      val inputRDD: RDD[String] = sc.textFile("input/words.txt")
      // 2. 处理数据,调用RDD中函数
      val resultRDD: RDD[(String, Int)] = inputRDD
        // 3.a 每行数据分割为单词
        .flatMap(line => line.split("\\s+"))
        // 3.b 转换为二元组,表示每个单词出现一次
        .map(word => (word, 1))
        // 3.c 按照Key分组聚合
        .reduceByKey((tmp, item) => tmp + item)
      // 3. 输出结果RDD保存到MySQL数据库
      resultRDD.foreach(println(_))
      resultRDD
        // 对结果RDD保存到外部存储系统时,考虑降低RDD分区数目
        .coalesce(1)
        // 对分区数据操作
        .foreachPartition{iter => saveToMySQL(iter)}
      // 应用程序运行结束,关闭资源
      sc.stop()
    }
    /**
     * 将每个分区中的数据保存到MySQL表中
     * @param datas 迭代器,封装RDD中每个分区的数据
     */
    def saveToMySQL(datas: Iterator[(String, Int)]): Unit = {
      println("哈哈1")
      // a. 加载驱动类
      Class.forName("com.mysql.cj.jdbc.Driver")
      // 声明变量
      var conn: Connection = null
      var pstmt: PreparedStatement = null

      try{
        // b. 获取连接
        conn = DriverManager.getConnection(
          "jdbc:mysql://node1.itcast.cn:3306/?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true",
          "root", "123456"
        )

        // c. 获取PreparedStatement对象
        val insertSql = "INSERT INTO db_test.tb_wordcount (word, count) VALUES(?, ?)"
        pstmt = conn.prepareStatement(insertSql)
        conn.setAutoCommit(false)
        // d. 将分区中数据插入到表中,批量插入
        datas.foreach{case (word, count) =>
          pstmt.setString(1, word)
          pstmt.setLong(2, count.toLong)
          // 加入批次
          pstmt.addBatch()
        }
        // TODO: 批量插入
        pstmt.executeBatch()
        conn.commit()

      }catch {
        case e: Exception => e.printStackTrace()
      }finally {
        if(null != pstmt) pstmt.close()
        if(null != conn) conn.close()
      }
    }
}

结果
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大数据老人家i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值