今天在测试spark3.0的过程中,将spark环境的Scala版本提高到2.12.x版本。
一开始我设置的是Scala版本是2.12.0
<properties>
<scala.version>2.12.0</scala.version>
<spark.version>3.0.0</spark.version>
</properties>
<dependencies>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.12</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.12</artifactId>
<version>${spark.version}</version>
</dependency>
</dependencies>
简单执行读取MySQL数据库的代码:
package com.gw.sparkSql
import java.util.Properties
import org.apache.spark.sql.{
DataFrame, SparkSession}
/**
* 利用sparksql从mysql表中读取数据
*/
object DataFromMysql {
def main(args: Array[String]): Unit = {
//创建sparkSession对象
val sparkSession: SparkSession = SparkSession.builder().master("local[4]").appName("DataFromMysql").getOrCreate()
//读取sql数据需要提前设置rul,table和properties
val data: DataFrame = sparkSession.read.format("jdbc")
.option("url", "jdbc:mysql://localhost:3306/test11")
.option("dbtable", "blood")
.option("user", "root")
.option("password", "123")
.load()
//获取数据
data.show()
data.printSchema()
//释放资源
sparkSession.stop()
}
}
结果执行报错:
Exception in thread "main" java.lang.NoSuchMethodError: scala.util.Properties$.coloredOutputEnabled()Z
at scala.reflect.internal.TypeDebugging$typeDebug$.<init>(TypeDebugging.scala:69)
at scala.reflect.internal.SymbolTable.typeDebug$lzycompute$1(SymbolTable.scala:28)
at scala.reflect.internal.SymbolTable.typeDebug(SymbolTable.scala:28)
at scala.reflect.runtime.JavaUniverseForce.force(JavaUniverseForce.scala:67)
at scala.reflect.runtime.JavaUniverseForce.force$(JavaUniverseForce.scala:18)
at scala.reflect.runtime.JavaUniverse.force(JavaUniverse.scala:30)
at scala.reflect.runtime.JavaUniverse.init(JavaUniverse.scala:162)
at scala.reflect.runtime.JavaUniverse.<init>(JavaUniverse.scala:93)
at scala.reflect.runtime.package$.universe$lzycompute(package.scala:29)
at scala.reflect.runtime.package$.universe(package.scala:29)
at org.apache.spark.sql.catalyst.ScalaReflection$.<init>(ScalaReflection.scala:50)
at org.apache.spark.sql.catalyst.ScalaReflection$.<clinit>(ScalaReflection.scala)
at org.apache.spark.sql.catalyst.encoders.RowEncoder$.serializerFor(RowEncoder.scala:77)
at org.apache.spark.sql.catalyst.encoders.RowEncoder$.apply(RowEncoder.scala:66)
at org.apache.spark.sql.Dataset$.$anonfun$ofRows$1(Dataset.scala:92)
at org.apache.spark.sql.SparkSession.withActive(SparkSession.scala:763)
at org.apache.spark.sql.Dataset$.ofRows(Dataset.scala:89)
at org.apache.spark.sql.SparkSession.baseRelationToDataFrame(SparkSession.scala:427)
at org.apache.spark.sql.DataFrameReader.loadV1Source(DataFrameReader.scala:279)
at org.apache.spark.sql.DataFrameReader.$anonfun$load$2(DataFrameReader.scala:268)
at scala.Option.getOrElse(Option.scala:121)
at org.apache.spark.sql.DataFrameReader.load(DataFrameReader.scala:268)
at org.apache.spark.sql.DataFrameReader.load(DataFrameReader.scala:203)
at com.gw.sparkSql.DataFromMysql$.main(DataFromMysql.scala:20)
at com.gw.sparkSql.DataFromMysql.main(DataFromMysql.scala)
百度之后发现仅有以下两篇文章涉及到这个问题,而且根本就没有解决方法。
https://stackoverflow.com/questions/60121386/what-dependencies-i-need-to-run-spark-read-csv-in-local-distribution#
https://stackoverflow.com/questions/59935502/java-lang-nosuchmethoderror-boolean-scala-util-properties-coloredoutputenable
没办法只能自己摸索了。
从错误类型来看,很明显示Scala的问题。我首先想到的是Scala2.12.x和Java的版本(我的是Java是1.8版本)对应问题,百度发现其实并不是这个原因。
然后开始针对Scala的版本下手,我首先将Scala的版本改成了:
<scala.version>2.12.1</scala.version>
还是报错。
然后我将Scala的版本改成了2.12.x中最新的版本:
<scala.version>2.12.12</scala.version>
很意外,完美运行。
以上是瞎猫碰上死耗子,下面是真正的原因分析。
原因分析:
凡是出现NoSuchMethodError一般只会有两种原因:
1、真正的依赖包的缺失,看缺少哪个添加哪个就可以了;
2、依赖包产生了冲突;
至于为什么jar包冲突会产生NoSuchMethodError,参考:
https://blog.csdn.net/ycccsdn/article/details/90549347?depth_1-
这里很明显就第二种原因。
首先回顾我们熟悉的spark2.x版本的依赖包,我一般都是用的2.2.0版本,多年以来下面这个写法一直没变,也就没有深究为什么是这样写:
<properties>
<scala.version>2.11.8</scala.version>
<spark.version>2.2.0</spark.version>
</properties>
其实Scala版本和spark版本之间是有对应关系的,这里我使用spark2.2.0,之所以Scala版本选择2.11.8是有原因的。
大家可以看一下spark-core依赖包中有什么?2.2.0版本的spark-core中是存在scala-library依赖的,版本也恰恰是2.11.8。
所以大家明白了吗,在升级spark3.0后,依赖包也不是随便写的:
我们来看一看spark3.0版本的spark-core包中存在的scala-library依赖是多少版本
所以到这里问题已经明了,只需将Scala版本和spark-core中的版本对应即可
<properties>
<scala.version>2.12.10</scala.version>
<spark.version>3.0.0</spark.version>
</properties>
Scala的版本只要大于等于2.12.10即可。